Отримати список підключених USB-пристроїв


92

Як отримати список усіх підключених USB-пристроїв на комп’ютері з ОС Windows?

Відповіді:


119

Додайте посилання на System.Management для вашого проекту, а потім спробуйте щось подібне:

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
Чи можна також отримати дружню назву пристрою? Наприклад, коли я заходжу у властивості мого USB-накопичувача, я бачу "USB-пристрій Kingston DataTraveler 2.0".
Роберт

1
У чому різниця між DeviceID та PNPDeviceID?
Shimmy Weitzhandler

1
Коли я запускаю вищезазначену програму, я отримую жорсткі диски USB, клавіатуру та мишу, але не отримую USB-камеру, USB-A / D. Чому не відображаються всі мої USB-пристрої?
Курт

8
його слід запитувати "Win32_USBControllerDevice", а не "Win32_USBHub", щоб отримати список усіх USB-пристроїв. Потім використовуйте властивість "Dependent", щоб отримати рядок адреси пристрою.
Недко

1
цей пошук займає у мене 8 секунд. Чи є можливість закріпити речі?
Даніель

45

Я знаю, що відповідаю на старе запитання, але я щойно пройшов те саме вправу і дізнався трохи більше інформації, яка, я думаю, буде багато сприяти дискусії та допомагати кожному, хто знайде це питання і побачить, де існуючі відповіді не підходять.

Загальноприйнятий відповідь близький, і може бути виправлено з допомогою коментаря Недко в до нього. Більш детальне розуміння задіяних класів WMI допомагає доповнити картину.

Win32_USBHubповертає лише концентратори USB . Це здається очевидним з огляду на минуле, але обговорення вище пропускає це. Він не включає всі можливі USB-пристрої, лише ті, які можуть (принаймні теоретично) виступати в ролі концентратора для додаткових пристроїв. У ньому відсутні деякі пристрої, які не є концентраторами (зокрема, частини композитних пристроїв).

Win32_PnPEntityвключає всі USB-пристрої та ще сотні пристроїв, що не мають USB. Порада Рассела Гантмана використовувати Win32_PnPEntityфільтр WHERE для пошуку DeviceID, що починається з "USB%", для фільтрування списку корисна, але дещо неповна; йому не вистачає пристроїв Bluetooth, деяких принтерів / серверів друку та HID-сумісних мишей та клавіатур. Я бачив "USB \%", "USBSTOR \%", "USBPRINT \%", "BTH \%", "SWD \%" та "HID \%". Win32_PnPEntityоднак є хорошим "головним" посиланням для пошуку інформації, як тільки у вас є PNPDeviceID з інших джерел.

Я знайшов найкращий спосіб перерахувати USB-пристрої - це запит Win32_USBControllerDevice. Хоча він не надає детальної інформації про пристрої, він повністю перераховує ваші USB-пристрої та надає вам пару PNPDeviceIDs антецедентів / залежностей для кожного USB-пристрою (включаючи концентратори, пристрої, що не є концентраторами, та пристрої, сумісні з HID) на вашому система. Кожен залежний, який повертається із запиту, буде USB-пристроєм. Антецедентом буде контролер, якому він призначений, один з контролерів USB, повернутий за запитом Win32_USBController.

Як бонус, здається, що під капотом WMI проходить по дереву пристроїв під час відповіді на Win32_USBControllerDeviceзапит, тому порядок повернення цих результатів може допомогти визначити стосунки батьків / дітей. (Це не задокументовано і, отже, лише здогадки; використовуйте CM_Get_Parent (або Child + Sibling ) API SetupDi для остаточних результатів.) Як опція для API SetupDi, схоже, для всіх перелічених нижче пристроїв Win32_USBHubїх можна шукати в реєстрі (at HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\ + PNPDeviceID) і матиме параметр, ParentIdPrefixякий буде префіксом останнього поля в PNPDeviceID його дочірніх елементів, тому це також може бути використано у підстановочному значенні для фільтрації Win32_PnPEntityзапиту.

У своїй заявці я зробив наступне:

  • (Необов’язково) Запитував Win32_PnPEntityі зберігав результати на карті ключ-значення (з PNPDeviceID як ключ) для подальшого отримання. Це необов’язково, якщо ви хочете пізніше робити окремі запити.
  • Запитували Win32_USBControllerDeviceостаточний список USB-пристроїв у моїй системі (усі залежні) та витягували PNPDeviceID з них. Я пішов далі, виходячи з порядку, що слідував за деревом пристроїв, призначити пристрої кореневому концентратору (повернуто перший пристрій, а не контролер) і побудував дерево на основі parentIdPrefix. Порядок, який повертає запит, який відповідає переліку дерев пристрою через SetupDi, - це кожен кореневий концентратор (для якого Antecedent ідентифікує контролер), а потім ітерація пристроїв під ним, наприклад, у моїй системі:
    • Кореневий концентратор першого контролера
    • Кореневий концентратор другого контролера
      • Перший концентратор під кореневим концентратором другого контролера (має parentIdPrefix)
        • Перший композитний пристрій під першим концентратором під кореневим концентратором другого контролера (PNPDeviceID збігається над ParentIdPrefix концентратора; має власний ParentIdPrefix)
          • Частина пристрою HID складеного пристрою (PNPDeviceID відповідає вище ParentIDPrefix композитного пристрою)
        • Другий пристрій під першим концентратором під кореневим концентратором другого контролера
          • HID Device частина композитного пристрою
      • Другий концентратор під кореневим концентратором другого контролера
        • Перший пристрій під другим концентратором під кореневим концентратором другого контролера
      • Третій концентратор під кореневим концентратором другого контролера
      • тощо
  • Запитано Win32_USBController. Це дало мені детальну інформацію про PNPDeviceIDs моїх контролерів, які знаходяться у верхній частині дерева пристроїв (які були попередниками попереднього запиту). Використовуючи дерево, отримане на попередньому кроці, рекурсивно ітерацію над його дочірніми (кореневими концентраторами) та їхніми дітьми (іншими концентраторами) та їхніми дітьми (нецентральними пристроями та композитними пристроями) та їхніми дітьми тощо.
    • Отримано деталі для кожного пристрою в моєму дереві шляхом посилання на карту, збережену на першому кроці. (За бажанням, можна пропустити перший крок і зробити Win32_PnPEntityіндивідуальний запит, використовуючи PNPDeviceId, щоб отримати інформацію на цьому кроці; можливо, компроміс між процесором і пам'яттю визначає, який порядок кращий.)

Підсумовуючи, Win32USBControllerDeviceзалежні - це повний перелік USB-пристроїв у системі (крім самих контролерів, які є попередниками в тому самому запиті), а також шляхом перехресного посилання на ці PNPDeviceIdпари з інформацією з реєстру та інших згаданих запитів, може бути побудована детальна картина.


Якби в одному було підключено 4 однакових сканера, як би ви розрізнили, який був, якби їх використовували, наприклад, у 4 різних операціях?
топшот

2
@topshot PNPDeviceID унікальний, якщо він підключений. Не було б способу визначити, чи ви відключили один і підключили другий ідентичний пізніше. Цей ідентифікатор також має перехресні посилання в інших областях, щоб сподіватися визначити, яка операція використовується.
Даніель Віддіс,

3
Якби в пристрої були вбудовані серійні номери, то їх можна було б диференціювати (це і є призначення серійних номерів). Серійний номер використовується як "ідентифікатор екземпляра" PnP. Якщо пристрій не містить серійний номер, тоді ідентифікатор екземпляра - це, по суті, шлях через дерево пристроїв від кореня до пристрою (і містить символи '&')
Брайан

Як запасний варіант, завжди спостерігається за списком пристроїв та від’єднується та підключається під час відстеження змін.
Технофіл

14

Щоб побачити пристрої, які мене зацікавили, я замінив Win32_USBHubїх Win32_PnPEntityу коді Адель Хазза на основі цього повідомлення . Це працює для мене:

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

Це спрацювало чудово. Щоб полегшити процес визначення пристрою, який ви щойно підключили, напишіть його, щоб він працював через певний проміжок часу, запишіть записи до словника та повідомте про будь-які доповнення з останнього запуску.
nixkuroi

7

Adel Hazzah в відповідь дає робочий код, Daniel Widdis - х і Недко в коментарі згадати , що вам потрібно запросити Win32_USBControllerDevice і використовувати його Dependent власності, і Деніел відповіді дає багато деталей без коду.

Ось узагальнення вищезазначеного обговорення, щоб надати робочий код, який перелічує безпосередньо доступні властивості пристрою PNP всіх підключених USB-пристроїв:

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

    }

}

Вам потрібно буде додати обробку винятків, якщо ви цього хочете. Зверніться до відповіді Даніеля, якщо ви хочете з’ясувати дерево пристроїв тощо.


5

Це набагато простіший приклад для людей, які шукають лише знімні USB-накопичувачі.

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
Також поверне дискету, ймовірно, пристрої зчитування карток USB, можливі накопичувачі Zip, Jazz та Orb
Mad Myche

Це ідеальне рішення для людей, які просто хочуть відповідати дружній назві USB. Я використовую цей приклад для резервного копіювання даних, і оскільки букву диска змінюється, мені потрібно шукати назву (тут drive.VolumeLabel)
Bio42

3

Якщо ви зміните ManagementObjectSearcher на наступне:

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

Тож "GetUSBDevices () виглядає так"

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

}

Результати будуть обмежені пристроями USB (на відміну від усіх типів у вашій системі)


1
Речення where, яке шукає ідентифікатори пристроїв, починаючи з USB, пропускає деякі елементи. Краще повторити залежних "Win32_USBControllerDevice"
Даніель Віддіс

2

Можливо, ця тема стане вам у нагоді. І ось проект коду Google, який це ілюструє (це P / Закликає setupapi.dll).


Ви уявляєте, чому клас ObjectQuery не має посилання, хоча я використовую System.Management?
Роберт

@ Роберт Ви додали посилання на проект? Ви можете зробити це, натиснувши правою кнопкою миші посилання у своєму проекті> Додати посилання ...> Шукати та перевіряти System.Management> OK.
Ернест

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

що це object valueробить?
newbieguy

Огляньте інші доступні властивості на диску та збережіть їх значення у вартості об’єкта
JxDarkAngel
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.