1

当 Windows 关闭时,我无法弄清楚为什么SvcShutdown()我的 win32 服务没有被调用。其他一切都完美无缺(停止、暂停/继续等)。在网上搜索了几个小时后,我什么也没找到。

任何帮助将非常非常感谢!

提前致谢,

詹姆士

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 = 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)
4

1 回答 1

0

看看这个:

[python-win32] win32 服务在重新启动时未收到关闭通知

于 2012-11-05T16:45:32.237 回答