C++ Win32 Not receiving DBT_DEVICEARRIVAL or DBT_DEVICEREMOVECOMPLETE on WM_DEVICECHANGE

后端 未结 1 1988
无人共我
无人共我 2021-02-05 23:42

I have been working on detecting USB insertion/removal. I have implemented code using CreateWindowEx(), passing a WNCLASSEX that with my window process callback. On inserting

相关标签:
1条回答
  • 2021-02-06 00:11

    If you read MSDN's documentation, it says:

    Detecting Media Insertion or Removal

    Windows sends all top-level windows a set of default WM_DEVICECHANGE messages when new devices or media (such as a CD or DVD) are added and become available, and when existing devices or media are removed. You do not need to register to receive these default messages. See the Remarks section in RegisterDeviceNotification for details on which messages are sent by default.

    RegisterDeviceNotification function

    Any application with a top-level window can receive basic notifications by processing the WM_DEVICECHANGE message. Applications can use the RegisterDeviceNotification function to register to receive device notifications.
    ...
    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_devicetype member is DBT_DEVTYP_PORT.

    DEV_BROADCAST_HDR structure

    DBT_DEVTYP_PORT
    0x00000003

    Port device (serial or parallel). This structure is a DEV_BROADCAST_PORT structure.

    A USB device is not a serial/parallel port. It is a Device Interface (DBT_DEVTYP_DEVICEINTERFACE) instead. And DBT_DEVICEARRIVAL/DBT_DEVICEREMOVECOMPLETE are not sent for DBT_DEVTYP_DEVICEINTERFACE devices by default. If you want them, you have to use RegisterDeviceNotification() to request them.

    It looks like your code is based on this MSDN example:

    Registering for Device Notification

    In that code, WceusbshGUID is defined as {25dbce51-6c8f-4a72-8a6d-b54c2b4fc835}, which is commented as being the class guid for USB serial host PnP drivers. According to this MSDN page:

    System-Defined Device Setup Classes Available to Vendors

    That guid is the class guid for Windows CE USB ActiveSync Devices (which is more consistent with the Wceusb... prefix used in the code). Also on that same page is {88BAE032-5A81-49f0-BC3D-A4FF138216D6} for USB Device (all USB devices that do not belong to another class).

    The following CodeProject article:

    Detecting Hardware Insertion and/or Removal

    Mentions {a5dcbf10-6530-11d2-901f-00c04fb951ed} for USB Raw Device. That same guid is documented on MSDN as GUID_DEVINTERFACE_USB_DEVICE (the naming of which probably stems back to pre-XP days when the naming of class guids and interface guids was not well separated).

    So when you call RegisterDeviceNotification() with a specific class guid, make sure it is the correct class guid, as you are going to get device events for only that specific type of device. It is likely that your USB device is using a different class guid than the one you are registering, and that is why you are not getting the device events you are expecting.

    If you want to detect any USB device regardless of its class guid (and there are several USB class guids defined), you can use the DEVICE_NOTIFY_ALL_INTERFACE_CLASSES flag when calling RegisterDeviceNotification(), then the class guid will be ignored. In the DBT_DEVICEARRIVAL and DBT_DEVICEREMOVECOMPLETE messages (assuming you are able to get them now), the reported dbcc_classguid will tell you the actual class guid, and the reported dbcc_name will begin with the \\?\USB: prefix.

    One last thing - you are only going to get DBT_DEVICE... messages if a USB device is inserted/removed while your app is already running. To detect if a USB device is already plugged in when your app starts, you have to use SetupAPI functions (SetupDiGetClassDevs(), SetupDiEnumDeviceInterfaces(), SetupDiGetDeviceInterfaceDetail(), etc) to enumerate the available devices.

    0 讨论(0)
提交回复
热议问题