Don't like ads? PRO users don't see any ads ;-)
Guest

Untitled

By: a guest on May 9th, 2012  |  syntax: None  |  size: 6.12 KB  |  hits: 19  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. Windows Service written in python, not detecting shutdown events and stopping gracefully
  2. from os.path import splitext, abspath
  3. from sys import modules
  4.  
  5. import win32serviceutil
  6. import win32service
  7. import win32event
  8. import win32api
  9. import win32security
  10. import win32ts
  11.  
  12. class Service(win32serviceutil.ServiceFramework):
  13.   _svc_name_ = '_unNamed'
  14.   _svc_display_name_ = '_Service Template'
  15.  
  16.   def __init__(self, *args):
  17.     win32serviceutil.ServiceFramework.__init__(self, *args)
  18.     self.log('Initializing Service')
  19.     self.stop_event = win32event.CreateEvent(None, 0, 0, None)
  20.     self.server = None
  21.  
  22.   def log(self, msg):
  23.     import servicemanager
  24.     servicemanager.LogInfoMsg(str(msg))
  25.   def logErr(self, msg):
  26.     import servicemanager
  27.     servicemanager.LogErrorMsg(str(msg))
  28.   def logWarn(self, msg):
  29.     import servicemanager
  30.     servicemanager.LogWarningMsg(str(msg))
  31.  
  32.   def sleep(self, sec):
  33.     win32api.Sleep(sec*1000, True)
  34.  
  35.   def GetAcceptedControls(self):
  36.     # Accept SESSION_CHANGE control
  37.     rc = win32serviceutil.ServiceFramework.GetAcceptedControls(self)
  38.     rc |= win32service.SERVICE_ACCEPT_SESSIONCHANGE
  39.     rc |= win32service.SERVICE_ACCEPT_SHUTDOWN
  40.     return rc
  41.  
  42.   def GetUserInfo(self, sess_id):
  43.     sessions = win32security.LsaEnumerateLogonSessions()[:-5]
  44.     for sn in sessions:
  45.       sn_info = win32security.LsaGetLogonSessionData(sn)
  46.       if sn_info['Session'] == sess_id:
  47.         return sn_info
  48.  
  49.   def getUserSessionInfo(self, sess_id):
  50.     msg = ""
  51.     try:
  52.       for key, val in self.GetUserInfo(sess_id).items():
  53.         msg += '%s : %sn'%(key, val)
  54.         if key == "UserName":
  55.           self.server.username = val
  56.     except Exception, e:
  57.       msg += '%s'%e
  58.     return msg
  59.  
  60.   # All extra events are sent via SvcOtherEx (SvcOther remains as a
  61.   # function taking only the first args for backwards compatability)
  62.   def SvcOtherEx(self, control, event_type, data):
  63.       # This is only showing a few of the extra events - see the MSDN
  64.       # docs for "HandlerEx callback" for more info.
  65.       if control == win32service.SERVICE_CONTROL_SESSIONCHANGE:
  66.           sess_id = data[0]
  67.           msg = ""
  68.           if event_type == 5: # logon
  69.             msg = "Logon event: type=%s, sessionid=%sn" % (event_type, sess_id)
  70. #            user_token = win32ts.WTSQueryUserToken(int(sess_id))
  71.             self.server.status = 1 #logon event
  72.             self.getUserSessionInfo(sess_id)
  73.             self.sendHeartbeat()
  74.             self.server.status = 2 #active user
  75.           elif event_type == 6: # logoff
  76.             msg = "Logoff event: type=%s, sessionid=%sn" % (event_type, sess_id)
  77.             self.server.status = 3 #logoff event
  78.             self.sendHeartbeat()
  79.             self.server.username = ""
  80.             self.server.status = 0 #no user
  81.           elif event_type == 7: # lock
  82.             msg = "Lock event: type=%s, sessionid=%sn" % (event_type, sess_id)
  83.             self.server.status = 1 #logon event
  84.             self.getUserSessionInfo(sess_id)
  85.             self.sendHeartbeat()
  86.             self.server.status = 2 #active user
  87.           elif event_type == 8: # unlock
  88.             self.server.status = 3 #logoff event
  89.             self.server.username = ""
  90.             self.sendHeartbeat()
  91.             self.server.status = 0 #no user
  92.           else:
  93.             msg = "Other session event: type=%s, sessionid=%sn" % (event_type, sess_id)
  94.  
  95. #          msg += self.getUserSessionInfo(sess_id)
  96.           self.log(msg)
  97. #      elif control == win32service.SERVICE_CONTROL_SHUTDOWN:
  98. #        msg = "Server being shutdown..."
  99. #        self.log(msg)
  100.  
  101.   def SvcDoRun(self):
  102.     self.ReportServiceStatus(win32service.SERVICE_START_PENDING)
  103.     try:
  104.       self.ReportServiceStatus(win32service.SERVICE_RUNNING)
  105.       self.log('Starting Service')
  106.       self.start()
  107.       self.log('Waiting')
  108.       win32event.WaitForSingleObject(self.stop_event, win32event.INFINITE)
  109.       self.log('Done')
  110.     except Exception, x:
  111.       self.logErr('Exception : %s' % x)
  112.       self.SvcStop()
  113.  
  114.   def SvcStop(self):
  115.     self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
  116.     self.log('Stopping Service')
  117.     self.stop()
  118.     self.log('Stopped')
  119.     win32event.SetEvent(self.stop_event)
  120.     self.ReportServiceStatus(win32service.SERVICE_STOPPED)
  121.  
  122.   def sendHeartbeat(self):
  123.     # 0 = no user, standard beat (format: 0||hostname)
  124.     # 1 = login event (format: 1|username|hostname)
  125.     # 2 = active user session
  126.     # 3 = logout event (format: 2|username|hostname)
  127.     # 4 = Service exception (format 3||hostname)
  128.     return self.server.sendHeartbeat(category=self.server.status, username=self.server.username)
  129.  
  130.   def start(self): pass
  131.   # to be overridden
  132.   def stop(self): pass
  133.   # to be overridden
  134.  
  135.   #reboot/halt makes a different call than 'net stop mytestservice'
  136.   def SvcShutdown(self):
  137.     msg = "Server being shutdown..."
  138.     self.log(msg)
  139.     self.SvcStop()
  140.  
  141.  
  142. def instart(cls, name, display_name=None, stay_alive=True, exe_name="caedmSAM.exe"):
  143.     '''
  144.         Install and  Start (auto) a Service
  145.  
  146.             cls : the class (derived from Service) that implement the Service
  147.             name : Service name
  148.             display_name : the name displayed in the service manager
  149.             stay_alive : Service will stop on logout if False
  150.     '''
  151.     cls._svc_name_ = name
  152.     cls._svc_display_name_ = display_name or name
  153.     cls._exe_name_ = exe_name
  154.     cls._svc_description_ = "CAEDM SAM Server registration and montioring service"
  155.     try:
  156.         module_path=modules[cls.__module__].__file__
  157.     except AttributeError:
  158.         # maybe py2exe went by
  159.         from sys import executable
  160.         module_path=executable
  161.     module_file=splitext(abspath(module_path))[0]
  162.     cls._svc_reg_class_ = '%s.%s' % (module_file, cls.__name__)
  163.     if stay_alive: win32api.SetConsoleCtrlHandler(lambda x: True, True)
  164.     try:
  165.         win32serviceutil.InstallService(
  166.                 cls._svc_reg_class_,
  167.                 cls._svc_name_,
  168.                 cls._svc_display_name_,
  169.                 startType=win32service.SERVICE_AUTO_START
  170.                 )
  171. #        print 'Install: OK'
  172.         win32serviceutil.StartService(
  173.                 cls._svc_name_
  174.                 )
  175. #        print 'Start: OK'
  176.     except Exception, x:
  177.         print str(x)