Annamalai Nagappan
Annamalai Nagappan

Reputation: 509

Python windows service "Error starting service: The service did not respond to the start or control request in a timely fashion"

I am running the code below by python win_service.py install from the normal command prompt, where I get access denied error.

Installing service TestService

Error installing service: Access is denied. (5)

which I was able to resolve when I started the command prompt by starting as administrator.

I was able to install the service, but I was unable to start the service.

Service installed

Starting service TestService

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

import win32serviceutil
import win32service
import win32event
import servicemanager
import socket

class AppServerSvc (win32serviceutil.ServiceFramework):
    _svc_name_ = "TestService"
    _svc_display_name_ = "Test Service"

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

    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_STARTED,
                              (self._svc_name_,''))
        self.main()

    def main(self):
        print "running"

if __name__ == '__main__':
    win32serviceutil.HandleCommandLine(AppServerSvc)

What am doing wrong, is there any other way to install the service that would solve the issue and how to dynamically run it as administrator.

Upvotes: 49

Views: 31528

Answers (10)

VLRoyrenn
VLRoyrenn

Reputation: 786

EDIT: As noted in my comment below, this shouldn't be needed anymore in pyWin32 305 and up, which automatically copies pythonservice.exe to sys.exec_prefix (i.e: inside your venv if you have one) and runs it from there.


As hinted by dslosky and this answer to a linked question, pythonservice.exe is going to run as a system service, so it will have a different environment than you do as a user. Running python service.py debug will run just fine because it's still running with your user environment, but if you run python service.py start, it could very well now fail instead due to the difference in environment variables. Your service timing out instantly is most likely due to pythonservice.exe failing to execute, and it will fail to execute it it's missing either PythonXX.dll or pywintypesXX.dll.

PythonXX.dll is likely to be in your system path already (depending on how Python was installed), but if you're juggling with several Python versions on the same system and trying to avoid altering the environment (like I unfortunately am), that's going to be a problem. I was hoping to get the service to use the venv by running something like .\.pyenv37\Scripts\python.exe service.py start, which works for regular Python scripts running as scheduled tasks, but you have to remember that service.py start only commands Windows to start the service. The actual service executable, pythonservice.exe, will actually resolve Python37.dll from the PATH variable, not the venv I was using when running service.py start. This means Python37.dll is no longer known when pythonservice.exe starts running as a system service, even though I have Python37.dll in my user PATH, as it is now running using the system PATH. Since pythonservice.exe can't run without Python37.dll, that causes an immediate linker error, and Windows reports it as an instant timeout.

The same goes for pywintypesXX.dll (pythonservice.exe will immediately timeout if it can't be found), except instead of installing it somewhere in your search path, the more portable solution is to drop it in the same directory as pythonservice.exe since the deafult DLL search path includes it.


EDIT: Here's what I'm using to verify all of that on script installation/update:

# customOptionHandler will only run after service install/update
if __name__=='__main__':
    win32serviceutil.HandleCommandLine(AppServerSvc, customOptionHandler=post_service_update)

.

def post_service_update(*args):
    import win32api, win32con, win32profile, pywintypes
    from contextlib import closing

    env_reg_key = "SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment"
    hkey = win32api.RegOpenKeyEx(win32con.HKEY_LOCAL_MACHINE, env_reg_key, 0, win32con.KEY_ALL_ACCESS)

    with closing(hkey):
        system_path = win32api.RegQueryValueEx(hkey, 'PATH')[0]
        # PATH may contain %SYSTEM_ROOT% or other env variables that must be expanded
        # ExpandEnvironmentStringsForUser(None) only expands System variables
        system_path = win32profile.ExpandEnvironmentStringsForUser(None, system_path)
        system_path_list = system_path.split(os.pathsep)

        core_dll_file = win32api.GetModuleFileName(sys.dllhandle)
        core_dll_name = os.path.basename(core_dll_file)

        for search_path_dir in system_path_list:
            try:
                dll_path = win32api.SearchPath(search_path_dir, core_dll_name)[0]
                print(f"System python DLL: {dll_path}")
                break
            except pywintypes.error as ex:
                if ex.args[1] != 'SearchPath': raise
                continue
        else:
            print("*** WARNING ***")
            print(f"Your current Python DLL ({core_dll_name}) is not in your SYSTEM PATH")
            print("The service is likely to not launch correctly.")

    from win32serviceutil import LocatePythonServiceExe
    pythonservice_exe = LocatePythonServiceExe()
    pywintypes_dll_file = pywintypes.__spec__.origin

    pythonservice_path = os.path.dirname(pythonservice_exe)
    pywintypes_dll_name = os.path.basename(pywintypes_dll_file)

    try:
        return win32api.SearchPath(pythonservice_path, pywintypes_dll_name)[0]
    except pywintypes.error as ex:
        if ex.args[1] != 'SearchPath': raise
        print("*** WARNING ***")
        print(f"{pywintypes_dll_name} is not is the same directory as pythonservice.exe")
        print(f'Copy "{pywintypes_dll_file}" to "{pythonservice_path}"')
        print("The service is likely to not launch correctly.")

It may seem like a lot, but it will at leastkeep you from forgetting to do those steps when deploying the service on a new machine/virtual environment or when updating python.

Upvotes: 5

Pushpender Singh
Pushpender Singh

Reputation: 127

I was also facing the same problem but, After messing out for 4 days, Finally I'm able to find the solution for this problem.

So, Here is the step by step Beginner Guide : https://github.com/PushpenderIndia/PythonWindowsService

Also Posting the same solution here as well.

Steps To Create an Python Windows Service

(1) Copy Paste These Codes to a Python File (e.g. server.py)

import servicemanager
import sys
import win32serviceutil
from mainserver import FlaskServer   # Import your code, I've written a module called mainserver which contains FlaskServer Code using OOPs
import threading
import concurrent.futures
import time

class workingthread(threading.Thread):
    def __init__(self, quitEvent):
        self.quitEvent = quitEvent
        self.waitTime = 1
        threading.Thread.__init__(self)

    def run(self):
        try:
            # Running start_flask() function on different thread, so that it doesn't blocks the code
            executor = concurrent.futures.ThreadPoolExecutor(max_workers=5)
            executor.submit(self.start_flask)
        except:
            pass

        # Following Lines are written so that, the program doesn't get quit
        # Will Run a Endless While Loop till Stop signal is not received from Windows Service API
        while not self.quitEvent.isSet():  # If stop signal is triggered, exit
            time.sleep(1)

    def start_flask(self):
        # This Function contains the actual logic, of windows service
        # This is case, we are running our flaskserver
        test = FlaskServer()
        test.start()

class FlaskService(win32serviceutil.ServiceFramework):
    _svc_name_ = "AA Testing"
    _svc_display_name_ = "AAA Testing"
    _svc_description_ = "This is my service"

    def __init__(self, args):
        win32serviceutil.ServiceFramework.__init__(self, args)
        self.hWaitStop = threading.Event()
        self.thread = workingthread(self.hWaitStop)

    def SvcStop(self):
        self.hWaitStop.set()

    def SvcDoRun(self):
        self.thread.start()
        self.hWaitStop.wait()
        self.thread.join()


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

(2) Install the latest pywin32.exe

  • NOTE: If you install pywin32 using pip, then it will not going to install properly, thus will show you some errors,
  • Visit https://github.com/mhammond/pywin32/releases
  • And Download the latest exe, If you are using Python 32bit then download pywin32-302.win32-py3.x.exe
  • If using Python 64 bit, then download pywin32-302.win-amd64-py3.x.exe

(3) Compile your server.py using pyinstaller

  • Compiling service executable
C:\Users\Pushpender\Desktop> python -m pip install servicemanager
C:\Users\Pushpender\Desktop> pyinstaller --onefile server.py --hidden-import=win32timezone --clean --uac-admin
  • Installing & Running service executable (Run CMD as Administrator)
C:\WINDOWS\system32>cd C:\Users\Pushpender\Desktop>
C:\WINDOWS\system32>d:
C:\Users\Pushpender\Desktop>server.exe --startup=auto install       # Installing service with startup == Automatic    
C:\Users\Pushpender\Desktop>server.exe start    # For starting service (You can start from Windows Service or From Task Manager)
C:\Users\Pushpender\Desktop>server.exe stop     # For stopping service (You can stop from Windows Service or From Task Manager)
C:\Users\Pushpender\Desktop>server.exe remove   # For removing installed service

(4) You can run server.py directly without compiling (Run CMD as Administrator)

C:\WINDOWS\system32>cd C:\Users\Pushpender\Desktop>
C:\WINDOWS\system32>d:
C:\Users\Pushpender\Desktop>python server.py --startup=auto install   # Installing service with startup == Automatic   
C:\Users\Pushpender\Desktop>python server.py start     # For starting service (You can start from Windows Service or From Task Manager)
C:\Users\Pushpender\Desktop>python server.py stop      # For stopping service (You can stop from Windows Service or From Task Manager)
C:\Users\Pushpender\Desktop>python server.py remove    # For removing installed service

NOTE:

  • You can tweak the above code, for example, you can change the following things

      _svc_display_name_ = "AAA Testing"
      _svc_description_ = "This is my service"
    
  • Also you can change the classes names of FlaskService , workingthread

  • Please change this line in your code from mainserver import FlaskServer

  • You can change the startup type to lots of things, type server.exe --help in order to know more about settings

  • If you want to set the StartUp= Manaull, then don't use --startup=auto, while installing service

  • If you want to set the StartUp= Automatic (Delayed), then use --startup=delayed, while installing service

  • Use --startup argument before install argument

(4) Integrate Windows server with Inno Setup Builder

  • If you want to create a Installer which will Install your service at Installion process & will remove it at Uninstall, then
  • Add these block of code in your script.iss
[Run]
Filename: "{app}\{#MyAppExeName}"; StatusMsg: "Installing Windows Service ... "; Parameters: "--startup=delayed install";  Flags: runhidden waituntilterminated  
Filename: "{app}\{#MyAppExeName}"; StatusMsg: "Running Windows Service ... "; Parameters: "start";  Flags: runhidden waituntilterminated

[UninstallRun]
Filename: "{app}\{#MyAppExeName}"; Parameters: "remove";  Flags: runhidden

Upvotes: 2

AzureIP
AzureIP

Reputation: 395

If you use embedded python on windows (portable python) add the folder to path.

C:\[...]\python-3.9.5-embed-amd64

This solved in my case.

Upvotes: 0

Chip
Chip

Reputation: 399

I know this is old but I was stuck on this forever. For me, this specific problem was solved by copying this file - pywintypes36.dll

From -> Python36\Lib\site-packages\pywin32_system32

To -> Python36\Lib\site-packages\win32

Upvotes: 39

Giuliano
Giuliano

Reputation: 81

Finally, the solution for this.

First step:

USE pyinstaller to create a standalone executable file, i.e.:

  pip install pyinstaller

  pyinstaller yourproject.py

  cd dist\yourproject

  yourproject.exe install

Second step:

Note that. When the Windows Service calls "your program", it gives a time to answer according the Service Development Protocol. All of the codes above, are not starting the service. Please, change your code as below:

if __name__ == '__main__':
   if len(sys.argv) > 1:
       # Called by Windows shell. Handling arguments such as: Install, Remove, etc.
       win32serviceutil.HandleCommandLine(JobManager)
   else:
       # Called by Windows Service. Initialize the service to communicate with the system operator
       servicemanager.Initialize()
       servicemanager.PrepareToHostSingle(JobManager)
       servicemanager.StartServiceCtrlDispatcher()

Upvotes: 8

Phantom
Phantom

Reputation: 41

Before you start debugging, I recommend to make sure that the two steps described at https://github.com/mhammond/pywin32, which are

pip install pywin32

and

python Scripts/pywin32_postinstall.py -install

were completed.

Upvotes: 2

haulpd
haulpd

Reputation: 273

Make sure you run the application with a different user than the default Local System user. Replace it with the user you successfully be able to run the debug command with.

  • To replace the user go to the windows services (start > services.msc)
  • Right click on the service you created > properties > Log On
  • Uncheck the Local System Account and enter your own.

from all python windows service can not start{error 1053} worked for me.

Because I just set PATH for user login, not for System. You can recheck your PATH for System Variables.

Upvotes: 1

Abhishek Gupta
Abhishek Gupta

Reputation: 1

Please ensure the below paths are added in your system variables path. The below paths are added for Python 3.7. ensure to add the path as per your python installed version.

C:\Users\1022226\AppData\Local\Programs\Python\Python37\Scripts C:\Users\1022226\AppData\Local\Programs\Python\Python37

Upvotes: 0

echo
echo

Reputation: 3124

if you are using anaconda python, be sure python36.dll is in your system path. This took me a long time to find.

credit: Can't start Windows service written in Python (win32serviceutil)

Upvotes: 1

dslosky
dslosky

Reputation: 1057

It's possible that your service is not starting because it's unable to find the executable. I had a similar issue that was solved by adding some pywin32 related directories to my system path. You can do this using setx:

setx /M PATH "%PATH%;C:\Python27;C:\Python27\Scripts;C:\Python27\Lib\site-packages\pywin32_system32;C:\Python27\Lib\site-packages\win32"

Try running this in a cmd window with admin privileges and adjust the paths to match your own python installation.

Upvotes: 11

Related Questions