I have a few services and I wanted to make a shared base class for them... however when I install a test subclass service, it fails with a useless error.
Here is the code:
import servicemanager
import win32serviceutil
import sys
import win32service
import win32event
class PythonServiceBase(win32serviceutil.ServiceFramework):
_svc_name_ = "SmallestPythonService"
_svc_display_name_ = "The smallest possible Python Service"
def __init__(self, args):
win32serviceutil.ServiceFramework.__init__(self, args)
# Create an event which we will use to wait on.
# The "service stop" request will set this event.
self.hWaitStop = win32event.CreateEvent(None, 0, 0, None)
def SvcStop(self):
# Before we do anything, tell the SCM we are starting the stop process.
self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
# And set my event.
win32event.SetEvent(self.hWaitStop)
def SvcDoRun(self):
# We do nothing other than wait to be stopped!
win32event.WaitForSingleObject(self.hWaitStop, win32event.INFINITE)
class BaselineService(PythonServiceBase):
_svc_name_ = "SmallestPythonService2"
_svc_display_name_ = "The smallest possible Python Service2"
def __init__(self, args):
super(BaselineService, self).__init__(args)
if __name__ == '__main__':
if len(sys.argv) == 1:
servicemanager.Initialize()
servicemanager.PrepareToHostSingle(BaselineService)
servicemanager.StartServiceCtrlDispatcher()
else:
win32serviceutil.HandleCommandLine(BaselineService)
Here's how I create and install:
pyinstaller -F --debug --hidden-import=win32timezone Baseline\baseline_service.py
dist\baseline_service.exe install && net start SmallestPythonService2
There are no tracebacks in the CMD output but this shows up:
The The smallest possible Python Service2 service is starting.
The The smallest possible Python Service2 service could not be started.
A service specific error occurred: 1.
More help is available by typing NET HELPMSG 3547.
Inside Event Viewer I see this:
- <Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
- <System>
<Provider Name="Python Service" />
<EventID Qualifiers="49152">10</EventID>
<Level>2</Level>
<Task>0</Task>
<Keywords>0x80000000000000</Keywords>
<TimeCreated SystemTime="2019-01-17T22:43:16.954038000Z" />
<EventRecordID>76457</EventRecordID>
<Channel>Application</Channel>
<Computer>DESKTOP-IM94TC5</Computer>
<Security />
</System>
- <EventData>
<Data><Error getting traceback - traceback.print_exception() failed</Data>
</EventData>
</Event>
Is pyinstaller just not capable of accurately passing subclass behavior to the EXE context?
If so, what are the pros/cons of the following alternative strategies:
Importing all shared methods from a "ServiceUtil" module to be used with my various services
Running a "ServiceHelper" on the same machine on which the true services run, and on
__init__
for each service, thy would consult this ServiceHelper to get back their shared behaviors (like the DoRun and Stop methods, etc.)