win32gui_devicenotify.py 3.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. # Demo RegisterDeviceNotification etc. Creates a hidden window to receive
  2. # notifications. See serviceEvents.py for an example of a service doing
  3. # that.
  4. import sys, time
  5. import win32gui, win32con, win32api, win32file
  6. import win32gui_struct, winnt
  7. # These device GUIDs are from Ioevent.h in the Windows SDK. Ideally they
  8. # could be collected somewhere for pywin32...
  9. GUID_DEVINTERFACE_USB_DEVICE = "{A5DCBF10-6530-11D2-901F-00C04FB951ED}"
  10. # WM_DEVICECHANGE message handler.
  11. def OnDeviceChange(hwnd, msg, wp, lp):
  12. # Unpack the 'lp' into the appropriate DEV_BROADCAST_* structure,
  13. # using the self-identifying data inside the DEV_BROADCAST_HDR.
  14. info = win32gui_struct.UnpackDEV_BROADCAST(lp)
  15. print("Device change notification:", wp, str(info))
  16. if wp==win32con.DBT_DEVICEQUERYREMOVE and info.devicetype==win32con.DBT_DEVTYP_HANDLE:
  17. # Our handle is stored away in the structure - just close it
  18. print("Device being removed - closing handle")
  19. win32file.CloseHandle(info.handle)
  20. # and cancel our notifications - if it gets plugged back in we get
  21. # the same notification and try and close the same handle...
  22. win32gui.UnregisterDeviceNotification(info.hdevnotify)
  23. return True
  24. def TestDeviceNotifications(dir_names):
  25. wc = win32gui.WNDCLASS()
  26. wc.lpszClassName = 'test_devicenotify'
  27. wc.style = win32con.CS_GLOBALCLASS|win32con.CS_VREDRAW | win32con.CS_HREDRAW
  28. wc.hbrBackground = win32con.COLOR_WINDOW+1
  29. wc.lpfnWndProc={win32con.WM_DEVICECHANGE:OnDeviceChange}
  30. class_atom=win32gui.RegisterClass(wc)
  31. hwnd = win32gui.CreateWindow(wc.lpszClassName,
  32. 'Testing some devices',
  33. # no need for it to be visible.
  34. win32con.WS_CAPTION,
  35. 100,100,900,900, 0, 0, 0, None)
  36. hdevs = []
  37. # Watch for all USB device notifications
  38. filter = win32gui_struct.PackDEV_BROADCAST_DEVICEINTERFACE(
  39. GUID_DEVINTERFACE_USB_DEVICE)
  40. hdev = win32gui.RegisterDeviceNotification(hwnd, filter,
  41. win32con.DEVICE_NOTIFY_WINDOW_HANDLE)
  42. hdevs.append(hdev)
  43. # and create handles for all specified directories
  44. for d in dir_names:
  45. hdir = win32file.CreateFile(d,
  46. winnt.FILE_LIST_DIRECTORY,
  47. winnt.FILE_SHARE_READ | winnt.FILE_SHARE_WRITE | winnt.FILE_SHARE_DELETE,
  48. None, # security attributes
  49. win32con.OPEN_EXISTING,
  50. win32con.FILE_FLAG_BACKUP_SEMANTICS | # required privileges: SE_BACKUP_NAME and SE_RESTORE_NAME.
  51. win32con.FILE_FLAG_OVERLAPPED,
  52. None)
  53. filter = win32gui_struct.PackDEV_BROADCAST_HANDLE(hdir)
  54. hdev = win32gui.RegisterDeviceNotification(hwnd, filter,
  55. win32con.DEVICE_NOTIFY_WINDOW_HANDLE)
  56. hdevs.append(hdev)
  57. # now start a message pump and wait for messages to be delivered.
  58. print("Watching", len(hdevs), "handles - press Ctrl+C to terminate, or")
  59. print("add and remove some USB devices...")
  60. if not dir_names:
  61. print("(Note you can also pass paths to watch on the command-line - eg,")
  62. print("pass the root of an inserted USB stick to see events specific to")
  63. print("that volume)")
  64. while 1:
  65. win32gui.PumpWaitingMessages()
  66. time.sleep(0.01)
  67. win32gui.DestroyWindow(hwnd)
  68. win32gui.UnregisterClass(wc.lpszClassName, None)
  69. if __name__=='__main__':
  70. # optionally pass device/directory names to watch for notifications.
  71. # Eg, plug in a USB device - assume it connects as E: - then execute:
  72. # % win32gui_devicenotify.py E:
  73. # Then remove and insert the device.
  74. TestDeviceNotifications(sys.argv[1:])