是的,您需要使用
RegisterDeviceNotificationWindows
API调用。据我所知,没有包装此功能的Python模块,因此您必须使用它
ctypes来调用此功能。
幸运的是,您不是第一个想要这样做的人,因此网上有一些代码示例。WxPython提供了一个代码示例,但是当您编写守护程序时,您可能对此并不感兴趣。您可能想尝试下面的代码示例,该示例依赖于
ctypes和
pywin32,从Tim
Golden毫不客气地进行了研究:
import win32serviceutilimport win32serviceimport win32eventimport servicemanagerimport win32guiimport win32gui_structstruct = win32gui_struct.structpywintypes = win32gui_struct.pywintypesimport win32conGUID_DEVINTERFACE_USB_DEVICE = "{A5DCBF10-6530-11D2-901F-00C04FB951ED}"DBT_DEVICEARRIVAL = 0x8000DBT_DEVICEREMOVECOMPLETE = 0x8004import ctypes## Cut-down clone of UnpackDEV_BROADCAST from win32gui_struct, to be# used for monkey-patching said module with correct handling# of the "name" param of DBT_DEVTYPE_DEVICEINTERFACE#def _UnpackDEV_BROADCAST (lparam): if lparam == 0: return None hdr_format = "iii" hdr_size = struct.calcsize (hdr_format) hdr_buf = win32gui.PyGetMemory (lparam, hdr_size) size, devtype, reserved = struct.unpack ("iii", hdr_buf) # Due to x64 alignment issues, we need to use the full format string over # the entire buffer. ie, on x64: # calcsize('iiiP') != calcsize('iii')+calcsize('P') buf = win32gui.PyGetMemory (lparam, size) extra = {} if devtype == win32con.DBT_DEVTYP_DEVICEINTERFACE: fmt = hdr_format + "16s" _, _, _, guid_bytes = struct.unpack (fmt, buf[:struct.calcsize(fmt)]) extra['classguid'] = pywintypes.IID (guid_bytes, True) extra['name'] = ctypes.wstring_at (lparam + struct.calcsize(fmt)) else: raise NotImplementedError("unknown device type %d" % (devtype,)) return win32gui_struct.DEV_BROADCAST_INFO(devtype, **extra)win32gui_struct.UnpackDEV_BROADCAST = _UnpackDEV_BROADCASTclass DeviceEventService (win32serviceutil.Serviceframework): _svc_name_ = "DevEventHandler" _svc_display_name_ = "Device Event Handler" _svc_description_ = "Handle device notification events" def __init__(self, args): win32serviceutil.Serviceframework.__init__ (self, args) self.hWaitStop = win32event.CreateEvent (None, 0, 0, None) # # Specify that we're interested in device interface # events for USB devices # filter = win32gui_struct.PackDEV_BROADCAST_DEVICEINTERFACE ( GUID_DEVINTERFACE_USB_DEVICE ) self.hDevNotify = win32gui.RegisterDeviceNotification ( self.ssh, # copy of the service status handle filter, win32con.DEVICE_NOTIFY_SERVICE_HANDLE ) # # Add to the list of controls already handled by the underlying # Serviceframework class. We're only interested in device events # def GetAcceptedControls(self): rc = win32serviceutil.Serviceframework.GetAcceptedControls (self) rc |= win32service.SERVICE_CONTROL_DEVICEEVENT return rc # # Handle non-standard service events (including our device broadcasts) # by logging to the Application event log # def SvcOtherEx(self, control, event_type, data): if control == win32service.SERVICE_CONTROL_DEVICEEVENT: info = win32gui_struct.UnpackDEV_BROADCAST(data) # # This is the key bit here where you'll presumably # do something other than log the event. Perhaps pulse # a named event or write to a secure pipe etc. etc. # if event_type == DBT_DEVICEARRIVAL: servicemanager.LogMsg ( servicemanager.EVENTLOG_INFORMATION_TYPE, 0xF000, ("Device %s arrived" % info.name, '') ) elif event_type == DBT_DEVICEREMOVECOMPLETE: servicemanager.LogMsg ( servicemanager.EVENTLOG_INFORMATION_TYPE, 0xF000, ("Device %s removed" % info.name, '') ) # # Standard stuff for stopping and running service; nothing # specific to device notifications # def SvcStop(self): self.ReportServiceStatus (win32service.SERVICE_STOP_PENDING) win32event.SetEvent (self.hWaitStop) def SvcDoRun(self): win32event.WaitForSingleObject (self.hWaitStop, win32event.INFINITE) servicemanager.LogMsg ( servicemanager.EVENTLOG_INFORMATION_TYPE, servicemanager.PYS_SERVICE_STOPPED, (self._svc_name_, '') )if __name__=='__main__': win32serviceutil.HandleCommandLine (DeviceEventService)
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)