Obtener la lista de dispositivos USB conectados

¿Cómo puedo obtener una lista de todos los dispositivos USB conectados en una computadora con Windows?

Agregue una referencia a System.Management para su proyecto, luego intente algo como esto:

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 GetUSBDevices() { List devices = new List(); 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; } } } 

Sé que estoy respondiendo a una vieja pregunta, pero acabo de pasar por este mismo ejercicio y descubrí un poco más de información, que creo que contribuirá mucho a la discusión y ayudará a cualquier otra persona que encuentre esta pregunta y vea dónde está el problema. las respuestas existentes se quedan cortas.

La respuesta aceptada es cercana, y se puede corregir usando el comentario de Nedko . Una comprensión más detallada de las clases de WMI implicadas ayuda a completar la imagen.

Win32_USBHub devuelve solo concentradores USB. Eso parece obvio en retrospectiva, pero la discusión anterior lo echa de menos. No incluye todos los dispositivos USB posibles, solo aquellos que pueden (en teoría, al menos) actuar como un centro para dispositivos adicionales. Pasa por alto algunos dispositivos que no son concentradores (especialmente partes de dispositivos compuestos).

Win32_PnPEntity incluye todos los dispositivos USB y cientos de dispositivos que no son USB. El consejo de Russel Gantman de utilizar una cláusula WHERE para buscar Win32_PnPEntity para un DeviceID que comience con “USB%” para filtrar la lista es útil pero ligeramente incompleto; falta dispositivos bluetooth, algunas impresoras / servidores de impresión y ratones y teclados compatibles con HID. He visto “USB \%”, “USBSTOR \%”, “USBPRINT \%”, “BTH \%”, “SWD \%” y “HID \%”. Win32_PnPEntity es, sin embargo, una buena referencia “maestra” para buscar información una vez que está en posesión del PNPDeviceID de otras fonts.

Lo que encontré fue que la mejor manera de enumerar dispositivos USB era consultar Win32_USBControllerDevice . Si bien no proporciona información detallada para los dispositivos, enumera por completo sus dispositivos USB y le proporciona un par Antecedentes / Dependientes de PNPDeviceID s para cada dispositivo USB (incluidos concentradores, dispositivos que no sean Hub y dispositivos compatibles con HID) en tu sistema. Cada Dependiente devuelto de la consulta será un Dispositivo USB. El Antecedente será el Controlador al que está asignado, uno de los Controladores USB devueltos al consultar Win32_USBController .

Como Win32_USBControllerDevice adicional, parece que bajo el capó, WMI recorre el árbol de dispositivos al responder a la consulta Win32_USBControllerDevice , por lo que el orden en que se devuelven estos resultados puede ayudar a identificar las relaciones padre / hijo. (Esto no está documentado y solo es una suposición; utilice CM_Get_Parent de la API de SetupDi (o Child + Sibling ) para obtener resultados definitivos). Como una opción para la API de SetupDi, parece que para todos los dispositivos enumerados en Win32_USBHub se pueden Win32_USBHub en el registro (en HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\ + PNPDeviceID ) y tendrá un parámetro ParentIdPrefix que será el prefijo del último campo en el PNPDeviceID de sus hijos, por lo que también podría usarse en una coincidencia de comodín para filtrar la consulta Win32_PnPEntity .

En mi solicitud, hice lo siguiente:

  • (Opcional) Se Win32_PnPEntity y se almacenaron los resultados en un mapa de clave-valor (con PNPDeviceID como clave) para su posterior recuperación. Esto es opcional si desea hacer consultas individuales más tarde.
  • Win32_USBControllerDevice para obtener una lista definitiva de dispositivos USB en mi sistema (todos los Dependientes) y extraje los PNPDeviceIDs de estos. Fui más lejos, según el orden que sigue el árbol de dispositivos, para asignar dispositivos al concentrador raíz (el primer dispositivo devuelto, en lugar del controlador) y construí un árbol basado en el parentIdPrefix. El orden que devuelve la consulta, que coincide con la enumeración del árbol del dispositivo a través de SetupDi, es cada núcleo raíz (para quien Antecedent identifica el controlador), seguido de una iteración de dispositivos debajo de él, por ejemplo, en mi sistema:
    • Concentrador de raíz del primer controlador
    • Concentrador raíz del segundo controlador
      • Primer concentrador bajo el concentrador raíz del segundo controlador (tiene parentIdPrefix)
        • Primer dispositivo compuesto en el primer concentrador bajo el concentrador raíz del segundo controlador (PNPDeviceID coincide con el ParentIdPrefix del concentrador, tiene su propio ParentIdPrefix)
          • Parte del dispositivo HID del dispositivo compuesto (PNPDeviceID coincide con el anterior ParentIDPrefix del dispositivo compuesto)
        • Segundo dispositivo bajo el primer concentrador debajo del concentrador raíz del segundo controlador
          • HID Dispositivo parte del dispositivo compuesto
      • Segundo concentrador debajo del concentrador raíz del segundo controlador
        • Primer dispositivo en el segundo concentrador en el concentrador raíz del segundo controlador
      • Tercer concentrador debajo del concentrador raíz del segundo controlador
      • etc.
  • Consultado Win32_USBController . Esto me dio la información detallada de los PNPDeviceIDs de mis controladores que se encuentran en la parte superior del árbol del dispositivo (que eran los Antecedentes de la consulta anterior). Utilizando el árbol derivado en el paso anterior, iterado recursivamente sobre sus hijos (los concentradores raíz) y sus hijos (los otros concentradores) y sus hijos (dispositivos no concentradores y dispositivos compuestos) y sus hijos, etc.
    • Obtuve detalles de cada dispositivo en mi árbol al hacer referencia al mapa almacenado en el primer paso. (Opcionalmente, uno podría omitir el primer paso y consultar Win32_PnPEntity individualmente usando PNPDeviceId para obtener la información en este paso, probablemente una compensación de CPU vs. memoria determinando qué orden es mejor).

En resumen, Win32USBControllerDevice Dependents es una lista completa de dispositivos USB en un sistema (además de los controladores mismos, que son los antecedentes en esa misma consulta), y al hacer una referencia cruzada de estos pares PNPDeviceId con información del registro y de las otras consultas mencionado, se puede construir una imagen detallada.

Para ver los dispositivos en los que estaba interesado, reemplacé Win32_USBHub por Win32_PnPEntity en el código de Adel Hazzah, basado en esta publicación . Esto funciona para mí:

 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 GetUSBDevices() { List devices = new List(); 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; } } } 

Si cambia el ManagementObjectSearcher a lo siguiente:

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

Así que el “GetUSBDevices () se ve así”

 static List GetUSBDevices() { List devices = new List(); 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; } 

}

Sus resultados estarán limitados a dispositivos USB (a diferencia de todos los tipos en su sistema)

Puede encontrar este hilo útil. Y aquí hay un proyecto de código de google que ejemplifica esto (es P / setupapi.dll en setupapi.dll ).

Este es un ejemplo mucho más simple para personas que solo buscan unidades usb extraíbles.

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

La respuesta de Adel Hazzah da un código de trabajo, los comentarios de Daniel Widdis y Nedko mencionan que necesitas consultar Win32_USBControllerDevice y usar su propiedad Dependiente, y la respuesta de Daniel da muchos detalles sin código.

Aquí hay una síntesis de la discusión anterior para proporcionar código de trabajo que enumera las propiedades de los dispositivos PNP directamente accesibles de todos los dispositivos USB conectados:

 using System; using System.Collections.Generic; using System.Management; // reference required namespace cSharpUtilities { class UsbBrowser { public static void PrintUsbDevices() { IList 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 GetUsbDevices() { IList usbDeviceAddresses = LookUpUsbDeviceAddresses(); List usbDevices = new List(); 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 LookUpUsbDeviceAddresses() { // this query gets the addressing information for connected USB devices ManagementObjectCollection usbDeviceAddressInfo = QueryMi(@"Select * from Win32_USBControllerDevice"); List usbDeviceAddresses = new List(); 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; } } } 

Tendrá que agregar el manejo de excepciones si lo desea. Consulte la respuesta de Daniel si desea averiguar el árbol del dispositivo y tal.