我正在通过正常命令提示符下的python win_service.py install运行下面的代码,在那里我得到访问被拒绝错误.
安装服务TestService
安装服务时出错:访问被拒绝.(5)
当我以管理员身份启动时,我能够解决这个问题.
我能够安装该服务,但我无法启动该服务.
已安装服务
启动服务TestService
启动服务时出错:服务未及时响应启动或控制请求.
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)
Run Code Online (Sandbox Code Playgroud)
出了什么问题,有没有其他方法来安装解决问题的服务以及如何以管理员的身份动态运行它.
小智 15
我知道这已经老了,但我永远坚持这个.对我来说,通过复制此文件解决了这个特定问题 - "pywintypes36.dll"
从 - > Python36\Lib\site-packages\pywin32_system32
要 - > Python36\Lib\site-packages\win32
有一篇很棒的文章 - > https://www.thepythoncorner.com/2018/08/how-to-create-windows-service-in-hi.html?m=1
您的服务可能无法启动,因为它无法找到可执行文件.我有一个类似的问题,通过添加一些pywin32相关的目录到我的系统路径解决.你可以这样做setx:
setx /M PATH "%PATH%;C:\Python27;C:\Python27\Scripts;C:\Python27\Lib\site-packages\pywin32_system32;C:\Python27\Lib\site-packages\win32"
Run Code Online (Sandbox Code Playgroud)
尝试在具有管理员权限的cmd窗口中运行此命令,并调整路径以匹配您自己的python安装.
最后,解决这个问题。
第一步:
使用 pyinstaller 创建独立的可执行文件,即:
pip install pyinstaller
pyinstaller yourproject.py
cd dist\yourproject
yourproject.exe install
Run Code Online (Sandbox Code Playgroud)
第二步:
注意。当Windows服务调用“你的程序”时,它会根据服务开发协议给出应答时间。上面的所有代码都没有启动服务。请更改您的代码如下:
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()
Run Code Online (Sandbox Code Playgroud)
编辑:正如我在下面的评论中所指出的,在 pyWin32 305 及更高版本中不再需要它,它会自动将 pythonservice.exe 复制到sys.exec_prefix(即:在您的 venv 中,如果有的话)并从那里运行它。
正如dslosky和链接问题的答案所暗示的那样, pythonservice.exe 将作为系统服务运行,因此它将具有与您作为用户不同的环境。运行python service.py debug会运行得很好,因为它仍然在您的用户环境中运行,但如果您运行python service.py start,它现在很可能会由于环境变量的差异而失败。您的服务立即超时很可能是由于 pythonservice.exe 无法执行,并且它将无法执行它,它缺少PythonXX.dll或pywintypesXX.dll。
PythonXX.dll可能已经在你的系统路径中(取决于 Python 的安装方式),但是如果你在同一系统上使用多个 Python 版本并试图避免改变环境(不幸的是,就像我一样),那么这将是一个问题。我希望通过运行类似的命令来让服务使用 venv .\.pyenv37\Scripts\python.exe service.py start,它适用于按计划任务运行的常规 Python 脚本,但您必须记住,service.py start只有命令 Windows 才能启动该服务。实际的服务可执行文件,pythonservice.exe实际上将从 PATH 变量解析 Python37.dll,而不是我在运行时使用的 venv service.py start。这意味着当 pythonservice.exe 开始作为系统服务运行时,Python37.dll 不再被识别,即使我的用户 PATH 中有 Python37.dll,因为它现在使用系统 PATH 运行。由于 pythonservice.exe 无法在没有 Python37.dll 的情况下运行,因此会立即导致链接器错误,并且 Windows 将其报告为即时超时。
这同样适用pywintypesXX.dll(如果找不到 pythonservice.exe 将立即超时),只不过不是将其安装在搜索路径中的某个位置,更便携的解决方案是将其放在与默认 DLL 搜索路径相同的pythonservice.exe目录中包括它。
编辑:这是我用来验证脚本安装/更新的所有内容的内容:
# customOptionHandler will only run after service install/update
if __name__=='__main__':
win32serviceutil.HandleCommandLine(AppServerSvc, customOptionHandler=post_service_update)
Run Code Online (Sandbox Code Playgroud)
。
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.")
Run Code Online (Sandbox Code Playgroud)
它可能看起来很多,但至少可以防止您在新机器/虚拟环境上部署服务或更新 python 时忘记执行这些步骤。
| 归档时间: |
|
| 查看次数: |
7158 次 |
| 最近记录: |