Skip to content

Instantly share code, notes, and snippets.

@J3ronimo
Last active August 16, 2019 13:35
Show Gist options
  • Save J3ronimo/a226f508bf92f7411c01cb318d9c8b77 to your computer and use it in GitHub Desktop.
Save J3ronimo/a226f508bf92f7411c01cb318d9c8b77 to your computer and use it in GitHub Desktop.
Windows service wrapper for Python scripts, using pywin32
"""
Usage:
python service.py install
Installs this script as a Windows service. Needs admin rights.
python service.py remove
Remove service. Needs admin rights.
"""
import sys
import win32serviceutil
import win32service
import win32event
import servicemanager
import socket
# get the application hosted in this service here:
import myapp
class AppServerSvc(win32serviceutil.ServiceFramework):
# enter your service meta info here:
_svc_name_ = _svc_display_name_ = "MyApp"
_svc_description_ = "Description of MyApp"
# configure service to start this script with the same python.exe
_exe_name_ = sys.executable # abspath to this python.exe
_exe_args_ = '"{}"'.format(__file__) # run this script in 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)
myapp.stop_server() # exchange with whatever stops your server
def SvcDoRun(self):
servicemanager.LogMsg(
servicemanager.EVENTLOG_INFORMATION_TYPE,
servicemanager.PYS_SERVICE_STARTED,
(self._svc_name_,'')
)
myapp.run_server() # exchange with whatever starts your server
if __name__ == '__main__':
if len(sys.argv) == 1:
# running as service => start server
servicemanager.Initialize()
servicemanager.PrepareToHostSingle(AppServerSvc)
servicemanager.StartServiceCtrlDispatcher()
else:
# running from cmdline => use win32's argparse
win32serviceutil.HandleCommandLine(AppServerSvc)
@J3ronimo
Copy link
Author

J3ronimo commented Aug 16, 2019

This avoids missing DLL errors by using python.exe directly as the service target instead of win32's pythonservice.exe. The main thing done in the latter are basically the 3 calls against servicemanager, which were taken over here into __main__ block.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment