serviceEvents.py 4.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. # A Demo of a service that takes advantage of the additional notifications
  2. # available in later Windows versions.
  3. # Note that all output is written as event log entries - so you must install
  4. # and start the service, then look at the event log for messages as events
  5. # are generated.
  6. # Events are generated for USB device insertion and removal, power state
  7. # changes and hardware profile events - so try putting your computer to
  8. # sleep and waking it, inserting a memory stick, etc then check the event log
  9. import win32serviceutil, win32service
  10. import win32event
  11. import servicemanager
  12. # Most event notification support lives around win32gui
  13. import win32gui, win32gui_struct, win32con
  14. GUID_DEVINTERFACE_USB_DEVICE = "{A5DCBF10-6530-11D2-901F-00C04FB951ED}"
  15. class EventDemoService(win32serviceutil.ServiceFramework):
  16. _svc_name_ = "PyServiceEventDemo"
  17. _svc_display_name_ = "Python Service Event Demo"
  18. _svc_description_ = "Demonstrates a Python service which takes advantage of the extra notifications"
  19. def __init__(self, args):
  20. win32serviceutil.ServiceFramework.__init__(self, args)
  21. self.hWaitStop = win32event.CreateEvent(None, 0, 0, None)
  22. # register for a device notification - we pass our service handle
  23. # instead of a window handle.
  24. filter = win32gui_struct.PackDEV_BROADCAST_DEVICEINTERFACE(
  25. GUID_DEVINTERFACE_USB_DEVICE)
  26. self.hdn = win32gui.RegisterDeviceNotification(self.ssh, filter,
  27. win32con.DEVICE_NOTIFY_SERVICE_HANDLE)
  28. # Override the base class so we can accept additional events.
  29. def GetAcceptedControls(self):
  30. # say we accept them all.
  31. rc = win32serviceutil.ServiceFramework.GetAcceptedControls(self)
  32. rc |= win32service.SERVICE_ACCEPT_PARAMCHANGE \
  33. | win32service.SERVICE_ACCEPT_NETBINDCHANGE \
  34. | win32service.SERVICE_CONTROL_DEVICEEVENT \
  35. | win32service.SERVICE_ACCEPT_HARDWAREPROFILECHANGE \
  36. | win32service.SERVICE_ACCEPT_POWEREVENT \
  37. | win32service.SERVICE_ACCEPT_SESSIONCHANGE
  38. return rc
  39. # All extra events are sent via SvcOtherEx (SvcOther remains as a
  40. # function taking only the first args for backwards compat)
  41. def SvcOtherEx(self, control, event_type, data):
  42. # This is only showing a few of the extra events - see the MSDN
  43. # docs for "HandlerEx callback" for more info.
  44. if control == win32service.SERVICE_CONTROL_DEVICEEVENT:
  45. info = win32gui_struct.UnpackDEV_BROADCAST(data)
  46. msg = "A device event occurred: %x - %s" % (event_type, info)
  47. elif control == win32service.SERVICE_CONTROL_HARDWAREPROFILECHANGE:
  48. msg = "A hardware profile changed: type=%s, data=%s" % (event_type, data)
  49. elif control == win32service.SERVICE_CONTROL_POWEREVENT:
  50. msg = "A power event: setting %s" % data
  51. elif control == win32service.SERVICE_CONTROL_SESSIONCHANGE:
  52. # data is a single elt tuple, but this could potentially grow
  53. # in the future if the win32 struct does
  54. msg = "Session event: type=%s, data=%s" % (event_type, data)
  55. else:
  56. msg = "Other event: code=%d, type=%s, data=%s" \
  57. % (control, event_type, data)
  58. servicemanager.LogMsg(
  59. servicemanager.EVENTLOG_INFORMATION_TYPE,
  60. 0xF000, # generic message
  61. (msg, '')
  62. )
  63. def SvcStop(self):
  64. self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
  65. win32event.SetEvent(self.hWaitStop)
  66. def SvcDoRun(self):
  67. # do nothing at all - just wait to be stopped
  68. win32event.WaitForSingleObject(self.hWaitStop, win32event.INFINITE)
  69. # Write a stop message.
  70. servicemanager.LogMsg(
  71. servicemanager.EVENTLOG_INFORMATION_TYPE,
  72. servicemanager.PYS_SERVICE_STOPPED,
  73. (self._svc_name_, '')
  74. )
  75. if __name__=='__main__':
  76. win32serviceutil.HandleCommandLine(EventDemoService)