user2851995
user2851995

Reputation: 23

How to obtain device's info from WM_DEVICECHANGE?

I'm working on a C# program to retrieve information of the device as soon as it is plugged in.

I want to ask that is there any ways to obtain a device's info (name, id, ...) based on the WM_DEVICECHANGE event that is fired when the device has been plugged in/out.

I tried looking into the WM_DEVICECHANGE's parameters but nothing in that contain info about the device.

Thanks in advance.

Upvotes: 2

Views: 8599

Answers (1)

Robin Krom
Robin Krom

Reputation: 320

I just answered something similar here: https://stackoverflow.com/a/57182910/1886251

Here are the details what you need to do:

To get device information via WM_DEVICECHANGE you need to call the Win32 API in user32.dll called RegisterDeviceNotification with a correctly filled DEV_BROADCAST_DEVICEINTERFACE_W struct.

If done so correctly you will get WM_DEVICECHANGE messages, which contain the event type (in our case DBT_DEVICEARRIVAL) as described in the Device Management Events, and a pointer to details. The pointer needs to be read as the DEV_BROADCAST_HDR struct , allowing you to recognise if this is indeed the DEV_BROADCAST_DEVICEINTERFACE_W struct. If so this struct will contain a device name, which you will need to parse at it contains the VID & PID.

That is quite a lot to process, and it took me a couple of hours to get it right. If you need a quick solution, and skip implementing the horrible details, add the NuGet package Dapplo.Windows.Messages (VID & PID are available with 0.9.7 and later) to your project and use the following code in a Windows Forms or WPF application:

    var deviceNotificationSubscription = DeviceNotification
        .OnDeviceArrival()
        .Subscribe(deviceInterfaceChangeInfo => {
            // Your code goes here, and will be automatically called
            var vid = deviceInterfaceChangeInfo.Device.VendorId;
            var pid = deviceInterfaceChangeInfo.Device.ProductId;
        });

My library highly depend on System.Reactive, I won't go into details here, which allows a more functional approach to your application. You can stop receiving the events by calling deviceNotificationSubscription.Dispose(); The library creates it's own hidden message window to receive the window messages, so you can even continue receiving the information in the background.

The Device property of the DeviceInterfaceChangeInfo has the DevBroadcastDeviceInterface struct, which contains the original Win32 information, but additionally has some higher level properties like:

  1. a friendly name, which is retrieved from the registry
  2. device type like USB, HID etc including an IsUSB
  3. vendor ID
  4. product ID
  5. a DeviceInterfaceClass enum for easier code access to the class
  6. a generated URL to get more information on the device

You can also register the OnDeviceRemoved, if you want to know what was removed.

Let me know if this works and helps here by and if you have any questions raise an issue on my Dapplo.Windows GitHub project! There is a lot more in this library but unfortunately most documentation still needs writing.

Upvotes: 0

Related Questions