Ottieni l'elenco dei dispositivi USB collegati


92

Come posso ottenere un elenco di tutti i dispositivi USB collegati su un computer Windows?

Risposte:


119

Aggiungi un riferimento a System.Management per il tuo progetto, quindi prova qualcosa di simile:

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

14
C'è un modo per recuperare anche il nome descrittivo del dispositivo? Ad esempio quando entro nelle proprietà della mia chiavetta usb vedo "Kingston DataTraveler 2.0 USB Device".
Robert

1
Qual è la differenza tra DeviceID e PNPDeviceID?
Shimmy Weitzhandler

1
Quando eseguo il programma sopra, ottengo i miei dischi rigidi USB, la mia tastiera e il mouse, ma non ricevo la mia fotocamera USB, il mio A / D USB. Perché non vengono visualizzati tutti i miei dispositivi USB?
Curt

8
dovrebbe essere richiesto "Win32_USBControllerDevice" e non "Win32_USBHub" per ricevere l'elenco di tutti i dispositivi USB. Quindi utilizzare la proprietà "Dependent" per ottenere la stringa dell'indirizzo del dispositivo.
Nedko

1
questa ricerca richiede 8 secondi per me. C'è la possibilità di sistemare le cose?
daniel

45

So di rispondere a una vecchia domanda, ma ho appena svolto lo stesso esercizio e ho scoperto un po 'più di informazioni, che penso contribuiranno molto alla discussione e aiuteranno chiunque trovi questa domanda e vedrà dove le risposte esistenti sono insufficienti.

La risposta accettata è vicina e può essere corretta utilizzando il commento di Nedko . Una comprensione più dettagliata delle classi WMI coinvolte aiuta a completare il quadro.

Win32_USBHubrestituisce solo hub USB . Ciò sembra ovvio con il senno di poi, ma la discussione di cui sopra manca. Non include tutti i possibili dispositivi USB, solo quelli che possono (in teoria, almeno) fungere da hub per dispositivi aggiuntivi. Mancano alcuni dispositivi che non sono hub (in particolare parti di dispositivi compositi).

Win32_PnPEntityinclude tutti i dispositivi USB e centinaia di altri dispositivi non USB. Il consiglio di Russel Gantman di utilizzare una clausola WHERE Win32_PnPEntityper cercare un DeviceID che inizia con "USB%" per filtrare l'elenco è utile ma leggermente incompleto; manca i dispositivi Bluetooth, alcune stampanti / server di stampa e mouse e tastiere compatibili con HID. Ho visto "USB \%", "USBSTOR \%", "USBPRINT \%", "BTH \%", "SWD \%" e "HID \%". Win32_PnPEntityè, tuttavia, un buon riferimento "master" per cercare informazioni una volta che si è in possesso del PNPDeviceID da altre fonti.

Quello che ho trovato è che il modo migliore per enumerare i dispositivi USB era interrogare Win32_USBControllerDevice. Sebbene non fornisca informazioni dettagliate per i dispositivi, enumera completamente i tuoi dispositivi USB e ti fornisce una coppia di antecedenti / dipendenti PNPDeviceIDper ogni dispositivo USB (inclusi Hub, dispositivi non Hub e dispositivi compatibili HID) sul tuo sistema. Ogni dipendente restituito dalla query sarà un dispositivo USB. L'antecedente sarà il controller a cui è assegnato, uno dei controller USB restituiti dalla query Win32_USBController.

Come bonus, sembra che sotto il cofano, WMI percorra la struttura dei dispositivi quando risponde alla Win32_USBControllerDevicequery, quindi l'ordine in cui vengono restituiti questi risultati può aiutare a identificare le relazioni padre / figlio. (Questo non è documentato ed è quindi solo una supposizione; usa CM_Get_Parent (o Child + Sibling ) dell'API SetupDi per risultati definitivi.) Come opzione per l'API SetupDi, sembra che per tutti i dispositivi elencati sotto Win32_USBHubpossano essere cercati nel registro (at HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\ + PNPDeviceID) e avrà un parametro ParentIdPrefixche sarà il prefisso dell'ultimo campo nel PNPDeviceID dei suoi figli, quindi questo potrebbe essere utilizzato anche in una corrispondenza con caratteri jolly per filtrare la Win32_PnPEntityquery.

Nella mia domanda, ho fatto quanto segue:

  • (Facoltativo) Query Win32_PnPEntitye memorizzazione dei risultati in una mappa valore-chiave (con PNPDeviceID come chiave) per il successivo recupero. Questo è facoltativo se desideri eseguire singole query in un secondo momento.
  • Ho chiesto Win32_USBControllerDeviceun elenco definitivo dei dispositivi USB sul mio sistema (tutti i dipendenti) ed ho estratto i PNPDeviceID di questi. Sono andato oltre, in base all'ordine che segue l'albero dei dispositivi, per assegnare i dispositivi all'hub principale (il primo dispositivo restituito, piuttosto che al controller) e ho costruito un albero basato su parentIdPrefix. L'ordine restituito dalla query, che corrisponde all'enumerazione dell'albero dei dispositivi tramite SetupDi, è ciascun hub principale (per il quale l'Antecedente identifica il controller), seguito da un'iterazione dei dispositivi sotto di esso, ad esempio, sul mio sistema:
    • Hub principale del primo controller
    • Hub principale del secondo controller
      • Primo hub sotto l'hub principale del secondo controller (ha parentIdPrefix)
        • Primo dispositivo composito sotto il primo hub sotto l'hub principale del secondo controller (PNPDeviceID corrisponde al ParentIdPrefix dell'hub; ha il proprio ParentIdPrefix)
          • Dispositivo HID parte del dispositivo composito (PNPDeviceID corrisponde al ParentIDPrefix del dispositivo composito sopra)
        • Secondo dispositivo sotto il primo hub sotto l'hub principale del secondo controller
          • Dispositivo HID parte del dispositivo composito
      • Secondo hub sotto l'hub principale del secondo controller
        • Primo dispositivo sotto il secondo hub sotto l'hub principale del secondo controller
      • Terzo hub sotto l'hub principale del secondo controller
      • eccetera.
  • Interrogato Win32_USBController. Questo mi ha fornito le informazioni dettagliate dei PNPDeviceID dei miei controller che si trovano nella parte superiore dell'albero dei dispositivi (che erano gli antecedenti della query precedente). Utilizzando l'albero derivato nel passaggio precedente, iterato ricorsivamente sui suoi figli (gli hub radice) e sui loro figli (gli altri hub) e sui loro figli (dispositivi non hub e dispositivi compositi) e sui loro figli, ecc.
    • Dettagli recuperati per ogni dispositivo nel mio albero facendo riferimento alla mappa memorizzata nel primo passaggio. (Facoltativamente, è possibile saltare il primo passaggio e interrogare Win32_PnPEntityindividualmente utilizzando PNPDeviceId per ottenere le informazioni in questo passaggio; probabilmente un compromesso tra CPU e memoria che determina quale ordine è migliore.)

In sintesi, i Win32USBControllerDevicedipendenti sono un elenco completo di dispositivi USB su un sistema (diversi dai controller stessi, che sono gli antecedenti nella stessa query) e facendo un riferimento incrociato a queste PNPDeviceIdcoppie con le informazioni del registro e delle altre query menzionate, si può costruire un'immagine dettagliata.


Se uno avesse 4 scanner identici collegati, come distingueresti quale era quale se fossero stati usati in 4 diverse operazioni, per esempio?
topshot

2
@topshot Il PNPDeviceID è unico fintanto che è connesso. Non ci sarebbe modo di sapere se ne hai scollegato uno e ne hai collegato un secondo identico in seguito. Questo ID è anche incrociato in altre aree per identificare, si spera, quale operazione viene utilizzata.
Daniel Widdis,

3
Se i dispositivi avessero numeri di serie incorporati, i dispositivi potrebbero essere differenziati (questo è lo scopo dei numeri di serie). Il numero di serie viene utilizzato come "ID istanza" PnP. Se il dispositivo non contiene un numero di serie, l'ID istanza è essenzialmente il percorso attraverso l'albero del dispositivo dalla radice al dispositivo (e contiene i caratteri "&")
Brian

Come ripiego, c'è sempre l'osservazione dell'elenco dei dispositivi e lo scollegamento e il ricollegamento durante la verifica delle modifiche.
Technophile

14

Per vedere i dispositivi che mi interessavano, ho dovuto sostituirli Win32_USBHubcon Win32_PnPEntitynel codice di Adel Hazzah, basato su questo post . Questo funziona per me:

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

Funzionava benissimo. Per rendere le cose facili per determinare quale dispositivo hai appena collegato, scrivilo per eseguirlo su un intervallo, scrivi le voci su un dizionario e segnala eventuali aggiunte dall'ultima volta che lo hai eseguito.
nixkuroi

7

La risposta di Adel Hazzah fornisce un codice funzionante, i commenti di Daniel Widdis e Nedko menzionano che è necessario interrogare Win32_USBControllerDevice e utilizzare la sua proprietà Dependent, e la risposta di Daniel fornisce molti dettagli senza codice.

Ecco una sintesi della discussione sopra per fornire un codice funzionante che elenca le proprietà del dispositivo PNP direttamente accessibili di tutti i dispositivi USB collegati:

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

    }

}

Dovrai aggiungere la gestione delle eccezioni se lo desideri. Consulta la risposta di Daniel se vuoi capire l'albero dei dispositivi e simili.


5

Questo è un esempio molto più semplice per le persone che cercano solo unità USB rimovibili.

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

2
Restituirà anche un floppy, probabilmente lettori di schede USB, possibili unità Zip, Jazz e Orb
Mad Myche

Questa è la soluzione ideale per le persone che desiderano semplicemente abbinare il nome descrittivo di una USB. Uso questo esempio per il backup dei dati e poiché la lettera dell'unità cambia, devo cercare il nome (qui drive.VolumeLabel)
Bio42

3

Se si modifica ManagementObjectSearcher nel seguente:

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

Quindi "GetUSBDevices () ha questo aspetto"

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

}

I risultati saranno limitati ai dispositivi USB (al contrario di tutti i tipi sul tuo sistema)


1
La clausola where che cerca gli ID dispositivo che iniziano con USB perde alcuni elementi. È meglio iterare i dipendenti di "Win32_USBControllerDevice"
Daniel Widdis

2

Potresti trovare utile questo thread . Ed ecco un progetto di codice Google che esemplifica questo (P / Invoca in setupapi.dll).


Hai idea del motivo per cui la classe ObjectQuery non ha un riferimento anche se sto usando System.Management?
Robert

@Robert hai aggiunto il riferimento al progetto? Puoi farlo facendo clic con il pulsante destro del mouse su Riferimenti nel progetto> Aggiungi riferimento ...> Cerca e seleziona Gestione sistema> 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);
                  }
             }
        }
   }

cosa fa object value?
newbieguy

Fai un tour delle altre proprietà disponibili su disco e salva il suo valore nel valore dell'oggetto
JxDarkAngel
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.