Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to identify what device was plugged into the USB slot?

I want to detect when the user plugs in or removes a USB sound card. I've managed to actually catch the event when this happens, but I can't tell what just got plugged in.

I tried an approach based on this question:

string query =
    "SELECT * FROM __InstanceCreationEvent " +
    "WITHIN 2 "
  + "WHERE TargetInstance ISA 'Win32_PnPEntity'";
var watcher = new ManagementEventWatcher(query);
watcher.EventArrived += new EventArrivedEventHandler(watcher_EventArrived);
watcher.Start();

While I get the notifications via the EventArrived event, I have no idea how to determine the actual name of the device that just got plugged in. I've gone through every property and couldn't make heads or tails out of it.

I also tried a different query:

var query = new WqlEventQuery("SELECT * FROM Win32_DeviceChangeEvent where EventType = 1 or EventType = 2");
var watcher = new ManagementEventWatcher(query);
watcher.EventArrived += watcher_EventArrived;
watcher.Stopped += watcher_Stopped;
watcher.Query = query;
watcher.Start();

but also to no avail. Is there a way to find the name of the device that got plugged in or removed.

The bottom line is that I'd like to know when a USB sound card is plugged in or removed from the system. It should work on Windows 7 and Vista (though I will settle for Win7 only).

EDIT: Based on the suggestions by the winning submitter, I've created a full solution that wraps all the functionality.

like image 723
AngryHacker Avatar asked May 18 '13 03:05

AngryHacker


3 Answers

If I use your first code, I can define my event like this:

    // define USB class guid (from devguid.h)
    static readonly Guid GUID_DEVCLASS_USB = new Guid("{36fc9e60-c465-11cf-8056-444553540000}");

    static void watcher_EventArrived(object sender, EventArrivedEventArgs e)
    {
        ManagementBaseObject instance = (ManagementBaseObject )e.NewEvent["TargetInstance"];
        if (new Guid((string)instance["ClassGuid"]) == GUID_DEVCLASS_USB)
        {
            // we're only interested by USB devices, dump all props
            foreach (var property in instance.Properties)
            {
                Console.WriteLine(property.Name + " = " + property.Value);
            }
        }
    }

And this will dump something like this:

Availability =
Caption = USB Mass Storage Device
ClassGuid = {36fc9e60-c465-11cf-8056-444553540000}
CompatibleID = System.String[]
ConfigManagerErrorCode = 0
ConfigManagerUserConfig = False
CreationClassName = Win32_PnPEntity
Description = USB Mass Storage Device
DeviceID = USB\VID_18A5&PID_0243\07072BE66DD78609
ErrorCleared =
ErrorDescription =
HardwareID = System.String[]
InstallDate =
LastErrorCode =
Manufacturer = Compatible USB storage device
Name = USB Mass Storage Device
PNPDeviceID = USB\VID_18A5&PID_0243\07072BE66DD78609
PowerManagementCapabilities =
PowerManagementSupported =
Service = USBSTOR
Status = OK
StatusInfo =
SystemCreationClassName = Win32_ComputerSystem
SystemName = KILROY_WAS_HERE

This should contain everything you need, including the device ID that you can get with something like instance["DeviceID"].

like image 187
Simon Mourier Avatar answered Oct 22 '22 17:10

Simon Mourier


EDIT 1: Oh is see that it is not a USB storage device but only a USB device. I will look for another solution.


Two links that describe the same problem:

http://hintdesk.com/c-catch-usb-plug-and-unplug-event/

http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/37123526-83fa-4e96-a767-715fe225bf28/

if (e.NewEvent.ClassPath.ClassName == "__InstanceCreationEvent")
{
    Console.WriteLine("USB was plugged in");
    //Get disk letter
    foreach (ManagementObject partition in new ManagementObjectSearcher(
"ASSOCIATORS OF {Win32_DiskDrive.DeviceID='" + mbo.Properties["DeviceID"].Value
+ "'} WHERE AssocClass = Win32_DiskDriveToDiskPartition").Get())
    {
        foreach (ManagementObject disk in new ManagementObjectSearcher(
                    "ASSOCIATORS OF {Win32_DiskPartition.DeviceID='"
                        + partition["DeviceID"]
                        + "'} WHERE AssocClass = Win32_LogicalDiskToPartition").Get())
        {
            Console.WriteLine("Disk=" + disk["Name"]);
        }
    }
}
like image 3
Odrai Avatar answered Oct 22 '22 18:10

Odrai


When I tried @AngryHacker solution, I noticed that the DeviceChangedEventArgs class did not ever get called, though. I removed it and just added Console.WriteLines() in the watcher_eventArrived methods.

Besides the deletion of the DeviceChangedEventArgs, here are my changes:

 (at line 46 in EstablishedWatchEvents)
 // setup the query to monitor removal
const string qryRemoval = "SELECT *" +  "FROM __InstanceDeletionEvent "
             + "WITHIN 2 " + "WHERE TargetInstance ISA 'Win32_PnPEntity' ";

 #region Events

 private void insertWatcher_EventArrived(object sender, EventArrivedEventArgs e)
 {

     var mbo = (ManagementBaseObject) e.NewEvent["TargetInstance"];
     if (new Guid((string) mbo["ClassGuid"]) == GUID_DEVCLASS_USB)
     {
         var deviceName = (string) mbo["Name"];
         Console.WriteLine(deviceName + " was inserted");

     }
 }

 private void removeWatcher_EventArrived(object sender, EventArrivedEventArgs e)
 {

     var mbo = (ManagementBaseObject)e.NewEvent["TargetInstance"];

     if (new Guid((string)mbo["ClassGuid"]) == GUID_DEVCLASS_USB)
     {
         var deviceName = (string)mbo["Name"];
         Console.WriteLine(deviceName + " was removed");
     }
 }

 #endregion
like image 2
VirginiaM1203 Avatar answered Oct 22 '22 17:10

VirginiaM1203