2013-05-18 2 views
12

Je souhaite détecter lorsque l'utilisateur branche ou supprime une carte son USB. J'ai réussi à attraper en fait l'événement lorsque cela se produit, mais je ne peux pas dire ce qui vient de se branchéComment identifier quel périphérique a été branché sur la fente USB?

J'ai essayé une approche basée sur 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(); 

Pendant que je reçois les notifications via l'événement EventArrived, je n'ai aucune idée de la façon de déterminer le nom réel de l'appareil qui vient d'être branché. J'ai traversé toutes les propriétés et je n'ai pas pu en faire la tête ou la queue.

J'ai essayé aussi une autre requête:

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(); 

mais aussi en vain. Est-il possible de trouver le nom de l'appareil qui a été branché ou retiré.

L'essentiel est que je voudrais savoir quand une carte son USB est branché ou retiré du système. Il devrait fonctionner sur Windows 7 et Vista (même si je me contenterai de Win7 uniquement).

EDIT: Sur la base des suggestions du soumissionnaire gagnant, j'ai créé un full solution qui englobe toutes les fonctionnalités.

+0

Qu'en est-il utiliser l'événement RegisterDeviceNotification? utilisé dans cette bibliothèque par exemple: https://code.google.com/p/winusbnet/ –

+0

@SimonMourier Cette bibliothèque semble être plus pour communiquer avec les périphériques USB plutôt que de les détecter. Je ne vois pas d'exemples qui montrent comment détecter les périphériques, et je ne vois rien dans l'API qui se prête à cette fin. – AngryHacker

Répondre

9

Si j'utilise votre premier code, je peux définir mon événement comme celui-ci:

// 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); 
      } 
     } 
    } 

Et cela videra quelque chose comme ceci:

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 

Cela devrait contenir tout ce dont vous avez besoin, y compris l'ID du périphérique que vous pouvez obtenir avec quelque chose comme instance["DeviceID"].

+0

Le deviceID est bon et bon, mais comment puis-je obtenir le nom du périphérique réel, par exemple. 'Casque USB Sennheiser'. – AngryHacker

+0

Avez-vous essayé d'exécuter ce code sans le contrôle GUID_DEVCLASS_USB que j'ai ajouté? Il peut être identifié comme un autre type (classe) d'appareil. Brancher un lecteur USB par exemple peut déclencher de nombreux événements (périphérique USB, disque dur, volume, etc.) –

+0

Oui, je l'ai fait, mais je suis confronté au même problème: il me donne tout sauf le nom réel du périphérique. – AngryHacker

3

EDIT 1: Oh, voyons que ce n'est pas un périphérique de stockage USB mais seulement un périphérique USB. Je vais chercher une autre solution.


Deux liens qui décrivent le même problème:

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"]); 
     } 
    } 
} 
0

Lorsque j'ai essayé la solution @AngryHacker, j'ai remarqué que la classe DeviceChangedEventArgs ne s'est jamais appelée. Je l'ai enlevé et juste ajouté Console.WriteLines() dans les méthodes watcher_eventArrived.

Outre la suppression de la DeviceChangedEventArgs, voici mes changements:

(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 
Questions connexes