[python-win32] Running a Windows Python service without pythonservice.exe?

Bill Janssen janssen at parc.com
Tue May 11 20:28:22 CEST 2010


OK, so I wrote my own InstallService:

--------------------------------------------------------------------------------
import sys, os, win32service

def InstallService(pythonClassFile, serviceName, displayName,
                   startType = None, errorControl = None, bRunInteractive = 0,
                   serviceDeps = None, userName = None, password = None,
                   exeArgs = None, description = None):

    # Handle the default arguments.
    if startType is None:
        startType = win32service.SERVICE_DEMAND_START
    serviceType = win32service.SERVICE_WIN32_OWN_PROCESS
    if bRunInteractive:
        serviceType = serviceType | win32service.SERVICE_INTERACTIVE_PROCESS
    if errorControl is None:
        errorControl = win32service.SERVICE_ERROR_NORMAL

    pythonClassFile = os.path.abspath(pythonClassFile)
    commandLine = '"%s" "%s"' % (sys.executable, pythonClassFile)
    if exeArgs:
        commandLine = commandLine + " " + exeArgs
    hscm = win32service.OpenSCManager(None,None,win32service.SC_MANAGER_ALL_ACCESS)
    try:
        hs = win32service.CreateService(
            hscm,
            serviceName,
            displayName,
            win32service.SERVICE_ALL_ACCESS,         # desired access
            serviceType,        # service type
            startType,
            errorControl,       # error control type
            commandLine,
            None,
            0,
            serviceDeps,
            userName,
            password)
        if description is not None:
            try:
                win32service.ChangeServiceConfig2(hs,win32service.SERVICE_CONFIG_DESCRIPTION,description)
            except NotImplementedError:
                pass    ## ChangeServiceConfig2 and description do not exist on NT
        win32service.CloseServiceHandle(hs)
    finally:
        win32service.CloseServiceHandle(hscm)

if __name__ == "__main__":
    if len(sys.argv) > 1 and os.path.exists(sys.argv[1]):
        InstallService(sys.argv[1], os.path.basename(sys.argv[1]), os.path.basename(sys.argv[1]))
--------------------------------------------------------------------------------

Note that it doesn't try to register the class string.  Seems to work:

$ python myinstallservice.py test2.py
$ sc query test2.py

SERVICE_NAME: test2.py
        TYPE               : 10  WIN32_OWN_PROCESS 
        STATE              : 1  STOPPED 
                                (NOT_STOPPABLE,NOT_PAUSABLE,IGNORES_SHUTDOWN)
        WIN32_EXIT_CODE    : 0	(0x0)
        SERVICE_EXIT_CODE  : 0	(0x0)
        CHECKPOINT         : 0x0
        WAIT_HINT          : 0x0
$ sc qc test2.py
[SC] GetServiceConfig SUCCESS

SERVICE_NAME: test2.py
        TYPE               : 10  WIN32_OWN_PROCESS 
        START_TYPE         : 3   DEMAND_START
        ERROR_CONTROL      : 1   NORMAL
        BINARY_PATH_NAME   : "c:\UpLib\1.7.9\python\python.exe" "c:\testrepo2\overhead\test2.py"  
        LOAD_ORDER_GROUP   :   
        TAG                : 0  
        DISPLAY_NAME       : test2.py  
        DEPENDENCIES       :   
        SERVICE_START_NAME : LocalSystem  
$

Although I think I should be crunching those paths to the "short" form.

However, it doesn't start:

$ sc start test2.py
[SC] StartService FAILED 1053:

The service did not respond to the start or control request in a timely fashion.
$

Here's what's in test2.py:

--------------------------------------------------------------------------------
import win32serviceutil
import win32service
import win32event
import win32evtlogutil
import servicemanager

class MyService(win32serviceutil.ServiceFramework):

   _svc_name_ = "test2.py"
   _svc_display_name_ = "test2.py"

   def __init__(self, args):
       win32serviceutil.ServiceFramework.__init__(self, args)
       self.hWaitStop = win32event.CreateEvent(None, 0, 0, None)

   def SvcStop(self):
       self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
       win32event.SetEvent(self.hWaitStop)

   def SvcDoRun(self):
       servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE,
                             servicemanager.PYS_SERVICE_STARTING,
                             (self._svc_name_, ""))
       while True:
           win32event.WaitForSingleObject(self.hWaitStop, 500)

servicemanager.Initialize()
servicemanager.PrepareToHostSingle(MyService)
win32serviceutil.HandleCommandLine(MyService)
--------------------------------------------------------------------------------

What am I missing here?

Bill


More information about the python-win32 mailing list