c# wmi usb-drive

c# - Busque la letra de la unidad USB de VID/PID(necesaria para XP y superior)



wmi usb-drive (3)

Así que pensé que incluiría la respuesta final aquí para que no tenga que darle sentido a esta publicación. Muchas gracias a Simon Mourier por tomarse el tiempo para resolver esto.

Mi codigo de trabajo

try { //Get a list of available devices attached to the USB hub List<string> disks = new List<string>(); var usbDevices = GetUSBDevices(); //Enumerate the USB devices to see if any have specific VID/PID foreach (var usbDevice in usbDevices) { if (usbDevice.DeviceID.Contains(USB_PID) && usbDevice.DeviceID.Contains(USB_VID)) { foreach (string name in usbDevice.GetDiskNames()) { //Open dialog to show file names textbox1.Text = name.ToString(); } } }

Así que solo use GetUSBDevices de mi pregunta original e incluya las dos clases mostradas por la respuesta de Simon Mourier, ¡y debería estar listo!

PREGUNTA ORIGINAL

Sé que esta pregunta se ha hecho antes (vea here ) pero ninguno de ellos tiene una respuesta confirmada y he intentado todas las respuestas sugeridas. Desafortunadamente, esos hilos llevan mucho tiempo muertos y esperaba que alguien pudiera dar una mejor respuesta aquí.

Hasta ahora tengo dos ''puntos de partida'', cada uno de los cuales mostraré a continuación.

OPCIÓN 1 : (obtiene VID / PID pero no letra de unidad)

Tengo un dispositivo integrado al que me conecto a través de una aplicación. Tengo un código que escanea con éxito cualquier dispositivo USB y revisa el VID/PID . Detecto con éxito mi dispositivo pero no tengo idea de cómo obtener la letra de la unidad. ¿Alguien me puede ayudar? Siento que podría agregar otra línea en la class pero cuando paso por Device Manager no puedo encontrar ninguna propiedad que describa la letra de la unidad.

¡Gracias!

Incluiré mi código hasta aquí abajo.

private void tsDownload_Click(object sender, EventArgs e) { var usbDevices = GetUSBDevices(); foreach (var usbDevice in usbDevices) { if (usbDevice.DeviceID.Contains(USB_PID) && usbDevice.DeviceID.Contains(USB_VID)) { //Find drive letter here } } }

donde esas funciones son:

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

y la clase es:

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

OPCIÓN 2 : (obtenga la letra de la unidad pero no VID / PID)

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()) { textBox1.Text = disk["Name"].ToString(); } } }

Voy a adivinar que el VID / PID está en una de las propiedades del objeto de disk , pero simplemente no puedo encontrar cuál.


Hay una antigua API de Win32 para la enumeración de dispositivos, solía ser parte de la API del instalador pero ha caído en desuso. Solo soy consciente de su existencia, no de su uso, pero espero que sea útil:

http://msdn.microsoft.com/en-us/library/windows/hardware/ff551015(v=vs.85).aspx

La estructura SP_DEVICE_INTERFACE_DETAIL es su objetivo final: tiene la ruta real del dispositivo. El camino para llegar allí, sin embargo ... Todo sería PInvoke, y bastante desagradable por las firmas, pero aquí hay algunas referencias:

Las firmas de PInvoke:

http://pinvoke.net/default.aspx/setupapi/SetupDiGetClassDevs.html http://pinvoke.net/default.aspx/setupapi/SetupDiEnumDeviceInterfaces.html http://pinvoke.net/default.aspx/setupapi/SetupDiGetDeviceInterfaceDetail.html

Los mapeos de la estructura:

http://pinvoke.net/default.aspx/Structures/SP_DEVICE_INTERFACE_DATA.html http://pinvoke.net/default.aspx/Structures/SP_DEVICE_INTERFACE_DETAIL_DATA.html

Ooh, encontré algunos ejemplos de uso (en C ++, pero bastante traducibles):

http://oroboro.com/usb-serial-number/


He tenido el mismo problema y también navegar por WMI no me ayudó, realmente.

Pero terminé con estas pocas líneas de código, y funciona muy bien para mí:

private string GetAvailableStorageDrive() { foreach (var info in System.IO.DriveInfo.GetDrives()) { if (info.DriveType == System.IO.DriveType.Removable && info.IsReady && !info.Name.Equals("A://")) { return info.Name; } } return string.Empty; }

Básicamente, la función anterior se ve si el tipo de DriveType es Removable y también si la unidad está lista. También excluyo la letra de la unidad ''A'' porque en los entornos de Windows predeterminados, este es el disquete.

Descripción de DriveType.Removable:

La unidad es un dispositivo de almacenamiento extraíble, como una unidad de disquete o una unidad flash USB.

Nota: como señaló CodeCaster, esta función también devolverá dispositivos de almacenamiento extraíbles, como SATA. Entonces, si ese es el caso, tendrá que buscar soluciones más complejas según lo provisto por otros.


Puede que me equivoque, pero parece que WMI no conoce la relación padre-hijo que existe en la API de configuración del dispositivo de Windows.

Por lo tanto, he creado una pequeña clase de utilidad de Device que puede agregar este enlace faltante desde la API de instalación nativa. Aquí es cómo lo usaría en su clase original de USBDeviceInfo :

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; } public IEnumerable<string> GetDiskNames() { using (Device device = Device.Get(PnpDeviceID)) { // get children devices foreach (string childDeviceId in device.ChildrenPnpDeviceIds) { // get the drive object that correspond to this id (escape the id) foreach (ManagementObject drive in new ManagementObjectSearcher("SELECT DeviceID FROM Win32_DiskDrive WHERE PNPDeviceID=''" + childDeviceId.Replace(@"/", @"//") + "''").Get()) { // associate physical disks with partitions foreach (ManagementObject partition in new ManagementObjectSearcher("ASSOCIATORS OF {Win32_DiskDrive.DeviceID=''" + drive["DeviceID"] + "''} WHERE AssocClass=Win32_DiskDriveToDiskPartition").Get()) { // associate partitions with logical disks (drive letter volumes) foreach (ManagementObject disk in new ManagementObjectSearcher("ASSOCIATORS OF {Win32_DiskPartition.DeviceID=''" + partition["DeviceID"] + "''} WHERE AssocClass=Win32_LogicalDiskToPartition").Get()) { yield return (string)disk["DeviceID"]; } } } } } } }

Y aquí está la nueva clase de dispositivos:

public sealed class Device : IDisposable { private IntPtr _hDevInfo; private SP_DEVINFO_DATA _data; private Device(IntPtr hDevInfo, SP_DEVINFO_DATA data) { _hDevInfo = hDevInfo; _data = data; } public static Device Get(string pnpDeviceId) { if (pnpDeviceId == null) throw new ArgumentNullException("pnpDeviceId"); IntPtr hDevInfo = SetupDiGetClassDevs(IntPtr.Zero, pnpDeviceId, IntPtr.Zero, DIGCF.DIGCF_ALLCLASSES | DIGCF.DIGCF_DEVICEINTERFACE); if (hDevInfo == (IntPtr)INVALID_HANDLE_VALUE) throw new Win32Exception(Marshal.GetLastWin32Error()); SP_DEVINFO_DATA data = new SP_DEVINFO_DATA(); data.cbSize = Marshal.SizeOf(data); if (!SetupDiEnumDeviceInfo(hDevInfo, 0, ref data)) { int err = Marshal.GetLastWin32Error(); if (err == ERROR_NO_MORE_ITEMS) return null; throw new Win32Exception(err); } return new Device(hDevInfo, data) {PnpDeviceId = pnpDeviceId}; } public void Dispose() { if (_hDevInfo != IntPtr.Zero) { SetupDiDestroyDeviceInfoList(_hDevInfo); _hDevInfo = IntPtr.Zero; } } public string PnpDeviceId { get; private set; } public string ParentPnpDeviceId { get { if (IsVistaOrHiger) return GetStringProperty(DEVPROPKEY.DEVPKEY_Device_Parent); uint parent; int cr = CM_Get_Parent(out parent, _data.DevInst, 0); if (cr != 0) throw new Exception("CM Error:" + cr); return GetDeviceId(parent); } } private static string GetDeviceId(uint inst) { IntPtr buffer = Marshal.AllocHGlobal(MAX_DEVICE_ID_LEN + 1); int cr = CM_Get_Device_ID(inst, buffer, MAX_DEVICE_ID_LEN + 1, 0); if (cr != 0) throw new Exception("CM Error:" + cr); try { return Marshal.PtrToStringAnsi(buffer); } finally { Marshal.FreeHGlobal(buffer); } } public string[] ChildrenPnpDeviceIds { get { if (IsVistaOrHiger) return GetStringListProperty(DEVPROPKEY.DEVPKEY_Device_Children); uint child; int cr = CM_Get_Child(out child, _data.DevInst, 0); if (cr != 0) return new string[0]; List<string> ids = new List<string>(); ids.Add(GetDeviceId(child)); do { cr = CM_Get_Sibling(out child, child, 0); if (cr != 0) return ids.ToArray(); ids.Add(GetDeviceId(child)); } while (true); } } private static bool IsVistaOrHiger { get { return (Environment.OSVersion.Platform == PlatformID.Win32NT && Environment.OSVersion.Version.CompareTo(new Version(6, 0)) >= 0); } } private const int INVALID_HANDLE_VALUE = -1; private const int ERROR_NO_MORE_ITEMS = 259; private const int MAX_DEVICE_ID_LEN = 200; [StructLayout(LayoutKind.Sequential)] private struct SP_DEVINFO_DATA { public int cbSize; public Guid ClassGuid; public uint DevInst; public IntPtr Reserved; } [Flags] private enum DIGCF : uint { DIGCF_DEFAULT = 0x00000001, DIGCF_PRESENT = 0x00000002, DIGCF_ALLCLASSES = 0x00000004, DIGCF_PROFILE = 0x00000008, DIGCF_DEVICEINTERFACE = 0x00000010, } [DllImport("setupapi.dll", SetLastError = true)] private static extern bool SetupDiEnumDeviceInfo(IntPtr DeviceInfoSet, uint MemberIndex, ref SP_DEVINFO_DATA DeviceInfoData); [DllImport("setupapi.dll", CharSet = CharSet.Unicode, SetLastError = true)] private static extern IntPtr SetupDiGetClassDevs(IntPtr ClassGuid, string Enumerator, IntPtr hwndParent, DIGCF Flags); [DllImport("setupapi.dll")] private static extern int CM_Get_Parent(out uint pdnDevInst, uint dnDevInst, uint ulFlags); [DllImport("setupapi.dll")] private static extern int CM_Get_Device_ID(uint dnDevInst, IntPtr Buffer, int BufferLen, uint ulFlags); [DllImport("setupapi.dll")] private static extern int CM_Get_Child(out uint pdnDevInst, uint dnDevInst, uint ulFlags); [DllImport("setupapi.dll")] private static extern int CM_Get_Sibling(out uint pdnDevInst, uint dnDevInst, uint ulFlags); [DllImport("setupapi.dll")] private static extern bool SetupDiDestroyDeviceInfoList(IntPtr DeviceInfoSet); // vista and higher [DllImport("setupapi.dll", SetLastError = true, EntryPoint = "SetupDiGetDevicePropertyW")] private static extern bool SetupDiGetDeviceProperty(IntPtr DeviceInfoSet, ref SP_DEVINFO_DATA DeviceInfoData, ref DEVPROPKEY propertyKey, out int propertyType, IntPtr propertyBuffer, int propertyBufferSize, out int requiredSize, int flags); [StructLayout(LayoutKind.Sequential)] private struct DEVPROPKEY { public Guid fmtid; public uint pid; // from devpkey.h public static readonly DEVPROPKEY DEVPKEY_Device_Parent = new DEVPROPKEY { fmtid = new Guid("{4340A6C5-93FA-4706-972C-7B648008A5A7}"), pid = 8 }; public static readonly DEVPROPKEY DEVPKEY_Device_Children = new DEVPROPKEY { fmtid = new Guid("{4340A6C5-93FA-4706-972C-7B648008A5A7}"), pid = 9 }; } private string[] GetStringListProperty(DEVPROPKEY key) { int type; int size; SetupDiGetDeviceProperty(_hDevInfo, ref _data, ref key, out type, IntPtr.Zero, 0, out size, 0); if (size == 0) return new string[0]; IntPtr buffer = Marshal.AllocHGlobal(size); try { if (!SetupDiGetDeviceProperty(_hDevInfo, ref _data, ref key, out type, buffer, size, out size, 0)) throw new Win32Exception(Marshal.GetLastWin32Error()); List<string> strings = new List<string>(); IntPtr current = buffer; do { string s = Marshal.PtrToStringUni(current); if (string.IsNullOrEmpty(s)) break; strings.Add(s); current += (1 + s.Length) * 2; } while (true); return strings.ToArray(); } finally { Marshal.FreeHGlobal(buffer); } } private string GetStringProperty(DEVPROPKEY key) { int type; int size; SetupDiGetDeviceProperty(_hDevInfo, ref _data, ref key, out type, IntPtr.Zero, 0, out size, 0); if (size == 0) return null; IntPtr buffer = Marshal.AllocHGlobal(size); try { if (!SetupDiGetDeviceProperty(_hDevInfo, ref _data, ref key, out type, buffer, size, out size, 0)) throw new Win32Exception(Marshal.GetLastWin32Error()); return Marshal.PtrToStringUni(buffer); } finally { Marshal.FreeHGlobal(buffer); } } }