Reputation: 509
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
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
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.
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)
pywin32-302.win32-py3.x.exe
pywin32-302.win-amd64-py3.x.exe
C:\Users\Pushpender\Desktop> python -m pip install servicemanager
C:\Users\Pushpender\Desktop> pyinstaller --onefile server.py --hidden-import=win32timezone --clean --uac-admin
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
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
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
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
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
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
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
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
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.
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
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
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
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