Hi All, For the life of me I cannot figure out why SvcShutdown() is not being called when the OS shuts down. All the other SCM notifications (pause/continue/stop) work just fine. I have searched high & low for solutions, but nothing. What appears to be a slam-dunk for others completely evades me. I must be missing something, so I bought a copy of Programming on Win32, but the Services section hasn't shed any more light on the issue, so I humbly ask for enlightenment. :-) What the heck am I missing??
Your help would be much appreciated! Thanks in advance, Rob ------------------------- import win32serviceutil import servicemanager import win32service import win32event import win32api import datetime LOGINFO = 0 LOGWARNING = 1 LOGERROR = 2 class MyService(win32serviceutil.ServiceFramework): _svc_name_ = 'MyService' _svc_display_name_ = 'MyService service' def __init__(self, *args): win32serviceutil.ServiceFramework.__init__(self, *args) # Create events for service stop, pause & continue # CreateEvent(securityAttrs, bManualReset, bInitialState, name) self.evStop = win32event.CreateEvent(None, 0, 0, None) self.evPause = win32event.CreateEvent(None, 0, 0, None) self.evContinue = win32event.CreateEvent(None, 0, 0, None) # Create event list for WaitForMultipleObjects() self.evhandles = self.evStop, self.evPause, self.evContinue # sigStatus must be this range for a valid SCM event self.validSignals = range(win32event.WAIT_OBJECT_0, win32event.MAXIMUM_WAIT_OBJECTS) # Signal ID returned from WFMO() else None self.sigStatus = None # Service run state. False means pausing/paused or stopping self.runState = True def logEvent(self, msg, logtype=LOGINFO, logcategory=None): import servicemanager if logtype == LOGINFO: servicemanager.LogInfoMsg(str(msg)) elif logtype == LOGWARNING: servicemanager.LogWarningMsg(str(msg)) elif logtype == LOGERROR: servicemanager.LogErrorMsg(str(msg)) def sleep(self, sec): '''A delay method sympathetic to SCM notifications.''' while sec > 0: # SCM event has taken place? if self.notificationFromSCM(): break win32api.Sleep(1000) sec -= 1 def notificationFromSCM(self): '''Returns True if SCM notification(s) have taken place. sigStatus has the value. Note: that calls to WaitForMultipleObjects() only returns the event status ONCE, after which it's reset (ie. calling it may return WAIT_OBJECT_0 and an immediate subsequent call will yield WAIT_TIMEOUT or similar.''' if self.sigStatus is not None: # Still have a live SCM event to process, so exit return True # WaitForMultipleObjects(handles, bWaitAll, dwMilliseconds) self.sigStatus = win32event.WaitForMultipleObjects(self.evhandles, 0, 0) if self.sigStatus in self.validSignals: return True else: # Timeout signal or similar, so MUST reset sigStatus self.sigStatus = None return False def SvcDoRun(self): self.ReportServiceStatus(win32service.SERVICE_START_PENDING) self.logEvent('Starting {0} Service...'.format(self._svc_display_name_)) self.ReportServiceStatus(win32service.SERVICE_RUNNING) self.logEvent('{0} Service started.'.format(self._svc_display_name_)) while True: if self.runState: try: # Insert service work activity here... self.logEvent('Working: {0}'.format(datetime.datetime.now())) self.sleep(10) except Exception as x: self.logEvent('Exception : {0}'.format(x), LOGERROR) else: self.sleep(30) # SCM notification? if self.notificationFromSCM(): if self.sigStatus == self.evhandles.index(self.evStop): # STOP event self.logEvent('Stopping {0} Service...'.format(self._svc_display_name_)) break elif self.sigStatus == self.evhandles.index(self.evPause): # PAUSE event self.logEvent('Pausing {0} Service...'.format(self._svc_display_name_)) self.runState = False # Other cleanup code here... self.logEvent('{0} Service paused.'.format(self._svc_display_name_)) self.ReportServiceStatus(win32service.SERVICE_PAUSED) elif self.sigStatus == self.evhandles.index(self.evContinue): # CONTINUE event self.logEvent('Resuming {0} service...'.format(self._svc_display_name_)) self.runState = True # Reset pause & continue to non-signaled state win32event.ResetEvent(self.evPause) win32event.ResetEvent(self.evContinue) # Other cleanup code here... self.logEvent('{0} Service started.'.format(self._svc_display_name_)) self.ReportServiceStatus(win32service.SERVICE_RUNNING) # Clear signal flag self.sigStatus = None # If we get here, then service has been stopped/shutdown self.logEvent('{0} Service stopped.'.format(self._svc_display_name_)) self.ReportServiceStatus(win32service.SERVICE_STOPPED) def SvcStop(self): self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING) # Signal STOP event win32event.SetEvent(self.evStop) def SvcPause(self): self.ReportServiceStatus(win32service.SERVICE_PAUSE_PENDING) # Signal PAUSE event win32event.SetEvent(self.evPause) def SvcContinue(self): self.ReportServiceStatus(win32service.SERVICE_CONTINUE_PENDING) # Signal CONTINUE event win32event.SetEvent(self.evContinue) def SvcShutdown(self): self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING) self.logEvent('**SvcShutdown event**') # Shutdown code here... win32event.SetEvent(self.evStop) _______________________________________________ python-win32 mailing list python-win32@python.org http://mail.python.org/mailman/listinfo/python-win32