Liste der angeschlossenen USB-Geräte abrufen

92

Wie kann ich eine Liste aller angeschlossenen USB-Geräte auf einem Windows-Computer abrufen?

Robert
quelle

Antworten:

118

Fügen Sie einen Verweis auf System.Management für Ihr Projekt hinzu und versuchen Sie Folgendes:

namespace ConsoleApplication1
{
  using System;
  using System.Collections.Generic;
  using System.Management; // need to add System.Management to your project references.

  class Program
  {
    static void Main(string[] args)
    {
      var usbDevices = GetUSBDevices();

      foreach (var usbDevice in usbDevices)
      {
        Console.WriteLine("Device ID: {0}, PNP Device ID: {1}, Description: {2}",
            usbDevice.DeviceID, usbDevice.PnpDeviceID, usbDevice.Description);
      }

      Console.Read();
    }

    static List<USBDeviceInfo> GetUSBDevices()
    {
      List<USBDeviceInfo> devices = new List<USBDeviceInfo>();

      ManagementObjectCollection collection;
      using (var searcher = new ManagementObjectSearcher(@"Select * From Win32_USBHub"))
        collection = searcher.Get();      

      foreach (var device in collection)
      {
        devices.Add(new USBDeviceInfo(
        (string)device.GetPropertyValue("DeviceID"),
        (string)device.GetPropertyValue("PNPDeviceID"),
        (string)device.GetPropertyValue("Description")
        ));
      }

      collection.Dispose();
      return devices;
    }
  }

  class USBDeviceInfo
  {
    public USBDeviceInfo(string deviceID, string pnpDeviceID, string description)
    {
      this.DeviceID = deviceID;
      this.PnpDeviceID = pnpDeviceID;
      this.Description = description;
    }
    public string DeviceID { get; private set; }
    public string PnpDeviceID { get; private set; }
    public string Description { get; private set; }
  }
}
Adel Hazzah
quelle
14
Gibt es eine Möglichkeit, auch den Anzeigenamen des Geräts abzurufen? Wenn ich zum Beispiel in die Eigenschaften meines USB-Sticks gehe, sehe ich "Kingston DataTraveler 2.0 USB Device".
Robert
1
Was ist der Unterschied zwischen DeviceID und PNPDeviceID?
Shimmy Weitzhandler
1
Wenn ich das obige Programm ausführe, bekomme ich meine USB-Festplatten, meine Tastatur und Maus, aber ich bekomme nicht meine USB-Kamera, meine USB-A / D. Warum werden nicht alle meine USB-Geräte angezeigt?
Curt
8
Es sollte "Win32_USBControllerDevice" und nicht "Win32_USBHub" abgefragt werden, um eine Liste aller USB-Geräte zu erhalten. Verwenden Sie dann die Eigenschaft "Abhängig", um die Geräteadresszeichenfolge abzurufen.
Nedko
1
Diese Suche dauert für mich 8 Sekunden. Gibt es eine Möglichkeit, Dinge zu befestigen?
Daniel
44

Ich weiß, dass ich auf eine alte Frage antworte, aber ich habe gerade dieselbe Übung durchlaufen und ein bisschen mehr Informationen herausgefunden, von denen ich denke, dass sie viel zur Diskussion beitragen und allen anderen helfen werden, die diese Frage finden und sehen, wo die Bestehende Antworten sind unzureichend.

Die akzeptierte Antwort ist nah und kann mit Nedkos Kommentar korrigiert werden . Ein detaillierteres Verständnis der beteiligten WMI-Klassen rundet das Bild ab.

Win32_USBHubGibt nur USB- Hubs zurück . Das scheint im Nachhinein offensichtlich, aber die obige Diskussion übersieht es. Es sind nicht alle möglichen USB-Geräte enthalten, sondern nur diejenigen, die (zumindest theoretisch) als Hub für zusätzliche Geräte fungieren können. Es fehlen einige Geräte, die keine Hubs sind (insbesondere Teile von Verbundgeräten).

Win32_PnPEntityEnthält alle USB-Geräte und Hunderte weiterer Nicht-USB-Geräte. Russel Gantmans Rat, eine WHERE-Klausel zu verwenden, um Win32_PnPEntitynach einer Geräte-ID zu suchen, die mit "USB%" beginnt, um die Liste zu filtern, ist hilfreich, aber etwas unvollständig. Es fehlen Bluetooth-Geräte, einige Drucker / Druckserver sowie HID-kompatible Mäuse und Tastaturen. Ich habe "USB \%", "USBSTOR \%", "USBPRINT \%", "BTH \%", "SWD \%" und "HID \%" gesehen. Win32_PnPEntityist jedoch eine gute "Master" -Referenz, um Informationen nachzuschlagen, sobald Sie im Besitz der PNPDeviceID aus anderen Quellen sind.

Was ich fand, war der beste Weg, um USB-Geräte aufzulisten, das Abfragen Win32_USBControllerDevice. Es enthält zwar keine detaillierten Informationen zu den Geräten, listet jedoch Ihre USB-Geräte vollständig auf und bietet Ihnen ein Antecedent / Dependent-Paar von PNPDeviceIDs für jedes USB-Gerät (einschließlich Hubs, Nicht-Hub-Geräte und HID-kompatible Geräte) auf Ihrem Gerät System. Jeder von der Abfrage zurückgegebene Abhängige ist ein USB-Gerät. Der Antecedent ist der Controller, dem er zugewiesen ist, einer der USB-Controller, die durch Abfrage zurückgegeben werden Win32_USBController.

Als Bonus scheint WMI unter der Haube den Gerätebaum zu durchlaufen, wenn auf die Win32_USBControllerDeviceAbfrage geantwortet wird. Die Reihenfolge, in der diese Ergebnisse zurückgegeben werden, kann daher dazu beitragen, Eltern-Kind-Beziehungen zu identifizieren. (Dies ist nicht dokumentiert und daher nur eine Vermutung. Verwenden Sie CM_Get_Parent (oder Child + Sibling ) der SetupDi-API für endgültige Ergebnisse.) Als Option für die SetupDi-API können anscheinend alle unter aufgeführten Geräte Win32_USBHubnachgeschlagen werden in der Registrierung (at HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\ + PNPDeviceID) und hat einen Parameter, ParentIdPrefixder das Präfix des letzten Felds in der PNPDeviceID seiner untergeordneten Felder ist, sodass dies auch in einem Platzhalterabgleich zum Filtern der Win32_PnPEntityAbfrage verwendet werden kann.

In meiner Bewerbung habe ich Folgendes getan:

  • (Optional) Abfrage Win32_PnPEntityund Speicherung der Ergebnisse in einer Schlüsselwertzuordnung (mit PNPDeviceID als Schlüssel) zum späteren Abrufen. Dies ist optional, wenn Sie später einzelne Abfragen durchführen möchten.
  • Abfrage Win32_USBControllerDevicenach einer endgültigen Liste der USB-Geräte auf meinem System (alle Abhängigen) und Extraktion der PNPDeviceIDs dieser. Ich ging weiter, basierend auf der Reihenfolge nach dem Gerätebaum, Geräte dem Root-Hub zuzuweisen (das erste zurückgegebene Gerät anstelle des Controllers) und erstellte einen Baum basierend auf dem parentIdPrefix. Die von der Abfrage zurückgegebene Reihenfolge, die der Gerätebaumaufzählung über SetupDi entspricht, ist jeder Root-Hub (für den der Antecedent den Controller identifiziert), gefolgt von einer Iteration der darunter liegenden Geräte, z. B. auf meinem System:
    • Root-Hub des ersten Controllers
    • Root-Hub des zweiten Controllers
      • Erster Hub unter dem Root-Hub des zweiten Controllers (hat parentIdPrefix)
        • Erstes zusammengesetztes Gerät unter dem ersten Hub unter dem Root-Hub des zweiten Controllers (PNPDeviceID stimmt mit dem ParentIdPrefix des Hubs überein; hat ein eigenes ParentIdPrefix)
          • HID-Geräteteil des zusammengesetzten Geräts (PNPDeviceID stimmt mit dem ParentIDPrefix des zusammengesetzten Geräts überein)
        • Zweites Gerät unter dem ersten Hub unter dem Root-Hub des zweiten Controllers
          • HID-Geräteteil des Composite-Geräts
      • Zweiter Hub unter dem Root-Hub des zweiten Controllers
        • Erstes Gerät unter dem zweiten Hub unter dem Root-Hub des zweiten Controllers
      • Dritter Hub unter dem Root-Hub des zweiten Controllers
      • etc.
  • Abgefragt Win32_USBController. Dies gab mir die detaillierten Informationen zu den PNPDeviceIDs meiner Controller, die sich oben im Gerätebaum befinden (die die Antezedenzien der vorherigen Abfrage waren). Verwenden Sie den im vorherigen Schritt abgeleiteten Baum, um rekursiv über seine untergeordneten Elemente (die Root-Hubs) und ihre untergeordneten Elemente (die anderen Hubs) und ihre untergeordneten Elemente (Nicht-Hub-Geräte und zusammengesetzte Geräte) und ihre untergeordneten Elemente usw. zu iterieren.
    • Details zu jedem Gerät in meinem Baum wurden abgerufen, indem auf die im ersten Schritt gespeicherte Karte verwiesen wurde. (Optional kann man den ersten Schritt überspringen und Win32_PnPEntityeinzeln mit der PNPDeviceId abfragen, um die Informationen in diesem Schritt zu erhalten. Wahrscheinlich ein Kompromiss zwischen CPU und Speicher, der bestimmt, welche Reihenfolge besser ist.)

Zusammenfassend ist Win32USBControllerDeviceDependents eine vollständige Liste der USB-Geräte auf einem System (mit Ausnahme der Controller selbst, die die Antecedents in derselben Abfrage sind), und durch Querverweise auf diese PNPDeviceIdPaare mit Informationen aus der Registrierung und den anderen genannten Abfragen. es kann ein detailliertes Bild erstellt werden.

Daniel Widdis
quelle
Wenn 4 identische Scanner angeschlossen wären, wie würden Sie unterscheiden, welche welche wären, wenn sie beispielsweise bei 4 verschiedenen Vorgängen verwendet würden?
Topshot
2
@topshot Die PNPDeviceID ist eindeutig, solange sie verbunden ist. Es ist nicht zu erkennen, ob Sie eine Verbindung getrennt und später eine zweite identische Verbindung hergestellt haben. Diese ID wird auch in anderen Bereichen referenziert, um hoffentlich zu identifizieren, welche Operation verwendet wird.
Daniel Widdis
3
Wenn die Geräte integrierte Seriennummern hätten, könnten die Geräte unterschieden werden (das ist der Zweck der Seriennummern). Die Seriennummer wird als PnP "Instanz-ID" verwendet. Wenn das Gerät keine Seriennummer enthält, ist die Instanz-ID im Wesentlichen der Pfad durch den Gerätebaum vom Stammverzeichnis zum Gerät (und enthält '&' Zeichen)
Brian
Als Fallback wird immer die Liste der Geräte beobachtet und der Stecker gezogen und wieder eingesteckt, während nach Änderungen gesucht wird.
Technophile
14

Um die Geräte sehe ich interessiert war, hatte ich ersetzen Win32_USBHubdurch Win32_PnPEntityin Adel Hazzah Kodex, basierend auf diesen Beitrag . Das funktioniert bei mir:

namespace ConsoleApplication1
{
  using System;
  using System.Collections.Generic;
  using System.Management; // need to add System.Management to your project references.

  class Program
  {
    static void Main(string[] args)
    {
      var usbDevices = GetUSBDevices();

      foreach (var usbDevice in usbDevices)
      {
        Console.WriteLine("Device ID: {0}, PNP Device ID: {1}, Description: {2}",
            usbDevice.DeviceID, usbDevice.PnpDeviceID, usbDevice.Description);
      }

      Console.Read();
    }

    static List<USBDeviceInfo> GetUSBDevices()
    {
      List<USBDeviceInfo> devices = new List<USBDeviceInfo>();

      ManagementObjectCollection collection;
      using (var searcher = new ManagementObjectSearcher(@"Select * From Win32_PnPEntity"))
        collection = searcher.Get();      

      foreach (var device in collection)
      {
        devices.Add(new USBDeviceInfo(
        (string)device.GetPropertyValue("DeviceID"),
        (string)device.GetPropertyValue("PNPDeviceID"),
        (string)device.GetPropertyValue("Description")
        ));
      }

      collection.Dispose();
      return devices;
    }
  }

  class USBDeviceInfo
  {
    public USBDeviceInfo(string deviceID, string pnpDeviceID, string description)
    {
      this.DeviceID = deviceID;
      this.PnpDeviceID = pnpDeviceID;
      this.Description = description;
    }
    public string DeviceID { get; private set; }
    public string PnpDeviceID { get; private set; }
    public string Description { get; private set; }
  }
}
Okrokette
quelle
Das hat super geklappt. Um die Ermittlung des gerade angeschlossenen Geräts zu vereinfachen, schreiben Sie es so, dass es in einem bestimmten Intervall ausgeführt wird, schreiben Sie die Einträge in ein Wörterbuch und melden Sie alle Ergänzungen aus der letzten Ausführung.
Nixkuroi
7

Adel Hazzah Die Antwort ergibt Code arbeiten, Daniel Widdis ist und Nedko der Kommentare erwähnen , dass Sie Win32_USBControllerDevice abfragen müssen, und nutzen seine Dependent - Eigenschaft und Daniels Antwort gibt viele Details , ohne Code.

Hier ist eine Synthese der obigen Diskussion, um einen Arbeitscode bereitzustellen, der die direkt zugänglichen PNP-Geräteeigenschaften aller angeschlossenen USB-Geräte auflistet:

using System;
using System.Collections.Generic;
using System.Management; // reference required

namespace cSharpUtilities
{
    class UsbBrowser
    {

        public static void PrintUsbDevices()
        {
            IList<ManagementBaseObject> usbDevices = GetUsbDevices();

            foreach (ManagementBaseObject usbDevice in usbDevices)
            {
                Console.WriteLine("----- DEVICE -----");
                foreach (var property in usbDevice.Properties)
                {
                    Console.WriteLine(string.Format("{0}: {1}", property.Name, property.Value));
                }
                Console.WriteLine("------------------");
            }
        }

        public static IList<ManagementBaseObject> GetUsbDevices()
        {
            IList<string> usbDeviceAddresses = LookUpUsbDeviceAddresses();

            List<ManagementBaseObject> usbDevices = new List<ManagementBaseObject>();

            foreach (string usbDeviceAddress in usbDeviceAddresses)
            {
                // query MI for the PNP device info
                // address must be escaped to be used in the query; luckily, the form we extracted previously is already escaped
                ManagementObjectCollection curMoc = QueryMi("Select * from Win32_PnPEntity where PNPDeviceID = " + usbDeviceAddress);
                foreach (ManagementBaseObject device in curMoc)
                {
                    usbDevices.Add(device);
                }
            }

            return usbDevices;
        }

        public static IList<string> LookUpUsbDeviceAddresses()
        {
            // this query gets the addressing information for connected USB devices
            ManagementObjectCollection usbDeviceAddressInfo = QueryMi(@"Select * from Win32_USBControllerDevice");

            List<string> usbDeviceAddresses = new List<string>();

            foreach(var device in usbDeviceAddressInfo)
            {
                string curPnpAddress = (string)device.GetPropertyValue("Dependent");
                // split out the address portion of the data; note that this includes escaped backslashes and quotes
                curPnpAddress = curPnpAddress.Split(new String[] { "DeviceID=" }, 2, StringSplitOptions.None)[1];

                usbDeviceAddresses.Add(curPnpAddress);
            }

            return usbDeviceAddresses;
        }

        // run a query against Windows Management Infrastructure (MI) and return the resulting collection
        public static ManagementObjectCollection QueryMi(string query)
        {
            ManagementObjectSearcher managementObjectSearcher = new ManagementObjectSearcher(query);
            ManagementObjectCollection result = managementObjectSearcher.Get();

            managementObjectSearcher.Dispose();
            return result;
        }

    }

}

Sie müssen die Ausnahmebehandlung hinzufügen, wenn Sie dies wünschen. Konsultieren Sie Daniels Antwort, wenn Sie den Gerätebaum und dergleichen herausfinden möchten.

Tydaeus
quelle
5

Dies ist ein viel einfacheres Beispiel für Leute, die nur nach austauschbaren USB-Laufwerken suchen.

using System.IO;

foreach (DriveInfo drive in DriveInfo.GetDrives())
{
    if (drive.DriveType == DriveType.Removable)
    {
        Console.WriteLine(string.Format("({0}) {1}", drive.Name.Replace("\\",""), drive.VolumeLabel));
    }
}
Baddack
quelle
2
Wird auch eine Diskette zurückgeben, wahrscheinlich USB-Kartenleser, mögliche Zip-, Jazz- und Orb-Laufwerke
Mad Myche
Dies ist die ideale Lösung für Leute, die nur den Anzeigenamen eines USB-Geräts suchen. Ich verwende dieses Beispiel für die Datensicherung und da sich der Laufwerksbuchstabe ändert, muss ich nach dem Namen suchen (hier drive.VolumeLabel)
Bio42
3

Wenn Sie den ManagementObjectSearcher wie folgt ändern:

ManagementObjectSearcher searcher = 
       new ManagementObjectSearcher("root\\CIMV2", 
       @"SELECT * FROM Win32_PnPEntity where DeviceID Like ""USB%"""); 

Das "GetUSBDevices () sieht also so aus"

static List<USBDeviceInfo> GetUSBDevices()
{
  List<USBDeviceInfo> devices = new List<USBDeviceInfo>();

  ManagementObjectCollection collection;
  using (var searcher = new ManagementObjectSearcher(@"SELECT * FROM Win32_PnPEntity where DeviceID Like ""USB%"""))
    collection = searcher.Get();      

  foreach (var device in collection)
  {
    devices.Add(new USBDeviceInfo(
    (string)device.GetPropertyValue("DeviceID"),
    (string)device.GetPropertyValue("PNPDeviceID"),
    (string)device.GetPropertyValue("Description")
    ));
  }

  collection.Dispose();
  return devices;
}

}}

Ihre Ergebnisse sind auf USB-Geräte beschränkt (im Gegensatz zu allen Typen auf Ihrem System).

Russell Gantman
quelle
1
In der where-Klausel, die nach Geräte-IDs sucht, die mit USB beginnen, fehlen einige Elemente. Es ist besser, die Abhängigkeiten von "Win32_USBControllerDevice" zu iterieren
Daniel Widdis
2

Du wirst vielleicht finden diesen Thread nützlich finden. Und hier ist ein Google-Code-Projekt, das dies veranschaulicht (es wird aufgerufen setupapi.dll).

Darin Dimitrov
quelle
Haben Sie eine Idee, warum die ObjectQuery-Klasse keine Referenz hat, obwohl ich System.Management verwende?
Robert
@ Robert hast du den Verweis zum Projekt hinzugefügt? Klicken Sie dazu in Ihrem Projekt mit der rechten Maustaste auf Referenzen> Referenz hinzufügen ...> Suchen und aktivieren Sie System.Management> OK.
Ernest
0
  lstResult.Clear();
  foreach (ManagementObject drive in new ManagementObjectSearcher("select * from Win32_DiskDrive where InterfaceType='USB'").Get())
  {
       foreach (ManagementObject partition in new ManagementObjectSearcher("ASSOCIATORS OF {Win32_DiskDrive.DeviceID='" + drive["DeviceID"] + "'} WHERE AssocClass = Win32_DiskDriveToDiskPartition").Get())
       {
            foreach (ManagementObject disk in new ManagementObjectSearcher("ASSOCIATORS OF {Win32_DiskPartition.DeviceID='" + partition["DeviceID"] + "'} WHERE AssocClass = Win32_LogicalDiskToPartition").Get())
            {
                  foreach (var item in disk.Properties)
                  {
                       object value = disk.GetPropertyValue(item.Name);
                  }
                  string valor = disk["Name"].ToString();
                  lstResult.Add(valor);
                  }
             }
        }
   }
JxDarkAngel
quelle
was bedeutet das object valuetun?
Newbieguy
Machen