Python Windows service pyinstaller executables error 1053

user1385894 picture user1385894 · Sep 10, 2014 · Viewed 14.7k times · Source

I have written a Windows service in python. If I run my script from the command prompt

python runService.py 

When I do this the service installs and starts correctly. I have been trying to create an executable using pyinstaller because i've seen the same issue with py2exe. When I run the .exe the service installs but does not start and I get the following error

error 1053 the service did not respond to the start or control request in a timely fashion 

I have seen that many people have had this issue but I can't seem to find a definitive answer as to how to fix this.

winservice.py

from os.path import splitext, abspath
from sys import modules, executable
from time import *
import win32serviceutil
import win32service
import win32event
import win32api

class Service(win32serviceutil.ServiceFramework):
    _svc_name_ = '_unNamed'
    _svc_display_name_ = '_Service Template'
    _svc_description_ = '_Description template'
    def __init__(self, *args):
        win32serviceutil.ServiceFramework.__init__(self, *args)
        self.log('init')
        self.stop_event = win32event.CreateEvent(None, 0, 0, None)

    #logs into the system event log
def log(self, msg):
    import servicemanager
    servicemanager.LogInfoMsg(str(msg))

def sleep(self, minute):
        win32api.Sleep((minute*1000), True)
def SvcDoRun(self):
    self.ReportServiceStatus(win32service.SERVICE_START_PENDING)
    try:
        self.ReportServiceStatus(win32service.SERVICE_RUNNING)
        self.log('start')
        self.start()
        self.log('wait')
        win32event.WaitForSingleObject(self.stop_event, win32event.INFINITE)
        self.log('done')
    except Exception, x:
        self.log('Exception : %s' % x)
        self.SvcStop()
def SvcStop(self):
    self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
    #self.log('stopping')
    self.stop()
    #self.log('stopped')
    win32event.SetEvent(self.stop_event)
    self.ReportServiceStatus(win32service.SERVICE_STOPPED)
# to be overridden
def start(self): pass
# to be overridden
def stop(self): pass

def instart(cls, name, description, display_name=None, stay_alive=True):
    ''' Install and  Start (auto) a Service

        cls : the class (derived from Service) that implement the Service
        name : Service name
        display_name : the name displayed in the service manager
        decription: the description 
        stay_alive : Service will stop on logout if False
    '''
    cls._svc_name_ = name
    cls._svc_display_name_ = display_name or name
    cls._svc_desciption_ = description
    try:
        module_path=modules[cls.__module__].__file__
    except AttributeError:

        module_path=executable
    module_file = splitext(abspath(module_path))[0]
    cls._svc_reg_class_ = '%s.%s' % (module_file, cls.__name__)
    if stay_alive: win32api.SetConsoleCtrlHandler(lambda x: True, True)
    try:
        win32serviceutil.InstallService(
            cls._svc_reg_class_,
            cls._svc_name_,
            cls._svc_display_name_,
            startType = win32service.SERVICE_AUTO_START,
            description = cls._svc_desciption_
        )
        print 'Install ok'
        win32serviceutil.StartService(
        cls._svc_name_
    )
    print 'Start ok'
except Exception, x:
    print str(x)

UPDATE

I resolved this issue by using py2exe but the same changes may work for pyinstaller too. I haven't had time to check this out myself.

I had to remove the instart function. Below is how my winservice.py reads now.

winservice_py2exe.py

from os.path import splitext, abspath
from sys import modules, executable
from time import *
import win32serviceutil
import win32service
import win32event
import win32api

class Service(win32serviceutil.ServiceFramework):
    _svc_name_ = 'actualServiceName' #here is now the name you would input as an arg for instart
    _svc_display_name_ = 'actualDisplayName' #arg for instart
    _svc_description_ = 'actualDescription'# arg from instart
    def __init__(self, *args):
        win32serviceutil.ServiceFramework.__init__(self, *args)
        self.log('init')
        self.stop_event = win32event.CreateEvent(None, 0, 0, None)

    #logs into the system event log
def log(self, msg):
    import servicemanager
    servicemanager.LogInfoMsg(str(msg))

def sleep(self, minute):
        win32api.Sleep((minute*1000), True)
def SvcDoRun(self):
    self.ReportServiceStatus(win32service.SERVICE_START_PENDING)
    try:
        self.ReportServiceStatus(win32service.SERVICE_RUNNING)
        self.log('start')
        self.start()
        self.log('wait')
        win32event.WaitForSingleObject(self.stop_event, win32event.INFINITE)
        self.log('done')
    except Exception, x:
        self.log('Exception : %s' % x)
        self.SvcStop()
def SvcStop(self):
    self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
    #self.log('stopping')
    self.stop()
    #self.log('stopped')
    win32event.SetEvent(self.stop_event)
    self.ReportServiceStatus(win32service.SERVICE_STOPPED)
# to be overridden
def start(self): pass
# to be overridden
def stop(self): pass

if __name__ == '__main__':
     # Note that this code will not be run in the 'frozen' exe-file!!!
     win32serviceutil.HandleCommandLine(VidiagService) #added from example included with py2exe

Below is the setup.py file i used with py2exe. This was taken from the example included with the py2exe installation:

setup.py

from distutils.core import setup
import py2exe
import sys
if len(sys.argv) == 1:
    sys.argv.append("py2exe")
    sys.argv.append("-q")

class Target:
    def __init__(self, **kw):
    self.__dict__.update(kw)
     # for the versioninfo resources
     self.version = "0.5.0"
     self.company_name = "No Company"
     self.copyright = "no copyright"
     self.name = "py2exe sample files"

 myservice = Target(
     # used for the versioninfo resource
     description = "A sample Windows NT service",
     # what to build.  For a service, the module name (not the
     # filename) must be specified!
     modules = ["winservice_py2exe"]
     )

 setup(
     options = {"py2exe": {"typelibs":
                      # typelib for WMI
                       [('{565783C6-CB41-11D1-8B02-00600806D9B6}', 0, 1, 2)],
                       # create a compressed zip archive
                       "compressed": 1,
                       "optimize": 2}},
     # The lib directory contains everything except the executables and the python dll.
     # Can include a subdirectory name.
     zipfile = "lib/shared.zip",

     service = [myservice]
    )

once you create the exe you can install the service from command using the following command

winservice_py2exe.exe -install

then to start the service you can use:

 net start aTest

or from windows service manager. All other windows command line functionality now works on the service as well as from windows service manager.

Answer

MrTorture picture MrTorture · Sep 19, 2014

Try changing the last few lines to

if __name__ == '__main__':
    if len(sys.argv) == 1:
        servicemanager.Initialize()
        servicemanager.PrepareToHostSingle(Service)
        servicemanager.StartServiceCtrlDispatcher()
    else:
        win32serviceutil.HandleCommandLine(Service)