Python windows service “Error starting service: Th

2020-02-02 08:05发布

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.

5条回答
欢心
2楼-- · 2020-02-02 08:38

As noted by Chip (and which I've missed while trying to figure this out), 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 may now fail instead due to the difference in environment variables. An instant timeout 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 like me and trying to be extra careful to not alter the environment, that's going to be a problem. I was running something like .\.pyenv37\Scripts\python.exe service.py start, gets Python37.dll from the PATH, not the venv like I assumed, so it's no longer known when pythonservice.exe starts running using a different PATH, which causes it to immediately fail Windows reports it as an instant timeout.

The same goes for pywintypesXX.dll, 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. It will also cause your service to immediately timeout if it if pythonservice.exe can't find it.

Figuring this out without any sort of logs is an absolute nightmare, let me tell you!


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.

查看更多
淡お忘
3楼-- · 2020-02-02 08:41

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

There's a great article about this -> https://www.thepythoncorner.com/2018/08/how-to-create-a-windows-service-in-python

查看更多
孤傲高冷的网名
4楼-- · 2020-02-02 08:53

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)

查看更多
相关推荐>>
5楼-- · 2020-02-02 08:58

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

查看更多
爱情/是我丢掉的垃圾
6楼-- · 2020-02-02 08:59

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.

查看更多
登录 后发表回答