Windows 的 Python 服务有几个问题

dan*_*nks 4 python windows service pywin32 pyinstaller

我已经检查了至少几十个与我类似的案例,但仍然没有提出解决方案,我希望有人能解释一下,这里一定有我遗漏的东西。

我正在使用 Python3.6 来创建一个 Windows 服务,如果它没有运行,该服务必须运行一个 .exe 文件。这是.py:

import win32service
import win32serviceutil
import win32api
import win32con
import win32event
import win32evtlogutil
import psutil
import subprocess
import os, sys, string, time
import servicemanager


class SLAAgent (win32serviceutil.ServiceFramework):
    _svc_name_ = "SLAAgent"
    _svc_display_name_ = "SLAAgent"

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

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

    def SvcDoRun(self):
        self.ReportServiceStatus(win32service.SERVICE_START_PENDING)
        self.ReportServiceStatus(win32service.SERVICE_RUNNING)
        servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE,servicemanager.PYS_SERVICE_STARTED,(self._svc_name_, ''))
        self._logger.info("Service Is Starting")
        main(self)

    def main(self):
        while self.isAlive:
            rc = win32event.WaitForSingleObject(self.hWaitStop, self.timeout)
            # Check to see if self.hWaitStop happened
            if rc == win32event.WAIT_OBJECT_0:
                servicemanager.LogInfoMsg("SLAAService has stopped")  #For Event Log
                break
            else:
                try:
                    s = subprocess.check_output('tasklist', shell=True)
                    if "SLA_Client.exe" in s:
                        pass
                    else:
                        pass
                        #execfile("SLA_Client.exe") #Execute the script
                except:
                    pass

if __name__ == '__main__':
    if len(sys.argv) == 1:
        servicemanager.Initialize()
        servicemanager.PrepareToHostSingle(SLAAgent)
        servicemanager.StartServiceCtrlDispatcher()
    else:
        win32serviceutil.HandleCommandLine(SLAAgent)
Run Code Online (Sandbox Code Playgroud)

我已经安装了 pywin32 包,将它们添加到 PATH 因为它在几个解决方案中被建议,并且还将 .dll 从 pywin32_system32 复制到 win32

环境变量 环境变量

事件查看器错误 事件查看器错误

事件查看器每次运行时都会打印此错误,无论是 python service.py 还是 python service.py start,控制台也会打印:

python SLA_Agent.py
Traceback (most recent call last):
  File "SLA_Agent.py", line 56, in <module>
    servicemanager.StartServiceCtrlDispatcher()
pywintypes.error: (1063, 'StartServiceCtrlDispatcher', 'The service process 
could not connect to the service controller.')
Run Code Online (Sandbox Code Playgroud)

当尝试从服务工具启动服务时,这是弹出的错误。我也看到了另一个错误,关于服务没有及时响应。

运行时出现服务错误

我试过用 pyinstaller 和 nuitka 编译它,错误是一样的。我不确定如何继续,我已经更改了代码以适合我使用 google 和 SO 找到的示例和解决方案,并且对方法和原因知之甚少。

如果有人以前遇到过这些问题,我非常感谢您的意见,到目前为止,其他答案对我没有帮助。

后期编辑:修复了代码缩进

dan*_*nks 5

这最终对我有用,除了代码中的差异之外,我并没有真正做任何特别的事情,经过几次尝试后,我可以使用 pyinstaller 进行编译并且service.exe install没有问题地运行。有一些人们可能不需要的额外日志记录行,但它们在调试和测试时派上用场。

非常感谢留下评论的每个人,他们非常有帮助,没有你就做不到 <3

import win32service, win32serviceutil, win32api, win32con, win32event, win32evtlogutil
import psutil
import subprocess
import os, sys, string, time, socket, signal
import servicemanager

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

    def __init__(self,args):
        win32serviceutil.ServiceFramework.__init__(self, *args)
        self.log('Service Initialized.')
        self.stop_event = win32event.CreateEvent(None, 0, 0, None)
        socket.setdefaulttimeout(60)


    def log(self, msg):
        servicemanager.LogInfoMsg(str(msg))

    def sleep(self, sec):
        win32api.Sleep(sec*1000, True)

    def SvcStop(self):
        self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
        self.stop()
        self.log('Service has stopped.')
        win32event.SetEvent(self.stop_event)
        self.ReportServiceStatus(win32service.SERVICE_STOPPED)

    def SvcDoRun(self):
        self.ReportServiceStatus(win32service.SERVICE_START_PENDING)
        try:
            self.ReportServiceStatus(win32service.SERVICE_RUNNING)
            self.log('Service is starting.')
            self.main()
            win32event.WaitForSingleObject(self.stop_event, win32event.INFINITE)
            servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE,servicemanager.PYS_SERVICE_STARTED,(self._svc_name_, ''))
        except Exception as e:
            s = str(e);
            self.log('Exception :'+s)
            self.SvcStop()

    def stop(self):
        self.runflag=False
        try:
            #logic
        except Exception as e:
            self.log(str(e))

    def main(self):
        self.runflag=True
        while self.runflag:
            rc = win32event.WaitForSingleObject(self.stop_event, 24*60*60)
            # Check to see if self.hWaitStop happened
            if rc == win32event.WAIT_OBJECT_0:
                self.log("Service has stopped")
                break
            else:
                try:
                    #logic
                except Exception as e:
                    self.log(str(e))

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