在WIN32 API中提供了一个RegisterNotification函数来接收系统发过来的message。本文介绍一下在csharp中调用该接口来监听特定GUID的设备消息。
在MSDN中,RegisterDeviceNotification的原型为
1 | HDEVNOTIFY WINAPI RegisterDeviceNotification( |
其中NotificationFilter起到消息过滤的作用,也就是说如果我们只想收到特定的消息,可以传递特定的NotificationFilter参数。
NotificationFilter [in]
A pointer to a block of data that specifies the type of device for which notifications should be sent. This block always begins with the DEV_BROADCAST_HDR structure. The data following this header is dependent on the value of the dbch_devicetype member, which can be DBT_DEVTYP_DEVICEINTERFACE or DBT_DEVTYP_HANDLE. For more information, see Remarks.
需要注意的是,对于PORT设备,arrival和removal消息会自动广播给顶层窗口。所以如果你的设备不是PORT设备,又想收到arrival和removal消息,需要手动注册消息监听。
The DBT_DEVICEARRIVAL and DBT_DEVICEREMOVECOMPLETE events are automatically broadcast to all top-level windows for port devices. Therefore, it is not necessary to call RegisterDeviceNotification for ports, and the function fails if the dbch_devicetypemember is DBT_DEVTYP_PORT. Volume notifications are also broadcast to top-level windows, so the function fails if dbch_devicetypeis DBT_DEVTYP_VOLUME. OEM-defined devices are not used directly by the system, so the function fails if dbch_devicetype is DBT_DEVTYP_OEM.
关于设备类型,猜测这个应该跟设备的驱动有关,在设备驱动中会指明设备的类型,然后在设备插入到系统中,会有一个枚举过程,这样系统就知道了该设备类型。上述的DBT_DEVICEARRIVAL和DBT_DEVICEREMOVECOMPLETE是WM_DEVICECHANGE消息中的参数。
如果设备类型为DBT_DEVTYP_DEVICEINTERFACE ,查看MSDN可知,该结构体中有一个guid的参数,正是我们需要的通过GUID来判断是否是特定设备的参数。我们在接受windows消息的函数中,判断是否是需要监测的设备即可。
1 | public void ProcessWinMessage(int msg, IntPtr wParam, IntPtr lParam) |
IsDesignedDevice
定义如下
1 | private bool IsDesiredDevice(IntPtr lParam) |
DEV_BROADCAST_HDR结构体中的三个字段包含在所有设备类型结构体中,所以可以先将WM_DEVICECHANGE中的lParam转化为DEV_BROADCAST_HDR类型,然后根据其dbch_devicetype
来转化为特定设备类型结构体类型,如DBT_DEVTYP_DEVICEINTERFACE
。
完整的例子请参考:UsbDetector