Dapatkan Daftar Perangkat USB yang terhubung

93

Bagaimana saya bisa mendapatkan daftar semua perangkat USB yang terhubung di komputer windows?

Robert
sumber

Jawaban:

122

Tambahkan referensi ke System.Management untuk proyek Anda, lalu coba sesuatu seperti ini:

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
sumber
14
Apakah ada cara untuk mendapatkan kembali nama perangkatnya? Misalnya ketika saya membuka properti stik usb saya, saya melihat "Perangkat USB Kingston DataTraveler 2.0".
Robert
2
Apa perbedaan antara DeviceID dan PNPDeviceID?
Shimmy Weitzhandler
1
Ketika saya menjalankan program di atas, saya mendapatkan Hard disk USB, keyboard dan mouse saya, tetapi saya tidak mendapatkan kamera USB saya, USB A / D saya. Mengapa tidak semua perangkat USB saya muncul?
Curt
8
itu harus ditanyai "Win32_USBControllerDevice" dan bukan "Win32_USBHub" untuk menerima daftar semua perangkat usb. Kemudian gunakan properti "Dependent" untuk mendapatkan string alamat perangkat.
Nedko
1
pencarian ini membutuhkan waktu 8 detik untuk saya. Apakah ada kemungkinan untuk mempercepat?
daniel
44

Saya tahu saya menjawab pertanyaan lama, tetapi saya baru saja melakukan latihan yang sama dan menemukan sedikit lebih banyak informasi, yang menurut saya akan berkontribusi banyak pada diskusi dan membantu siapa pun yang menemukan pertanyaan ini dan melihat di mana jawaban yang ada gagal.

The jawaban yang diterima dekat, dan dapat diperbaiki menggunakan komentar Nedko ini untuk itu. Pemahaman yang lebih rinci tentang Kelas WMI yang terlibat membantu melengkapi gambaran tersebut.

Win32_USBHubhanya mengembalikan Hub USB . Tampaknya sudah jelas di belakang, tetapi pembahasan di atas meleset. Ini tidak mencakup semua perangkat USB yang memungkinkan, hanya yang dapat (setidaknya secara teori) bertindak sebagai hub untuk perangkat tambahan. Ini merindukan beberapa perangkat yang bukan hub (terutama bagian dari perangkat komposit).

Win32_PnPEntitytidak mencakup semua perangkat USB, dan ratusan perangkat non-USB lainnya. Saran Russel Gantman untuk menggunakan pencarian klausa WHERE Win32_PnPEntityuntuk DeviceID yang diawali dengan "USB%" untuk memfilter daftar sangat membantu tetapi sedikit tidak lengkap; itu merindukan perangkat bluetooth, beberapa printer / server cetak, dan mouse dan keyboard yang sesuai dengan HID. Saya telah melihat "USB \%", "USBSTOR \%", "USBPRINT \%", "BTH \%", "SWD \%", dan "HID \%". Win32_PnPEntityadalah, bagaimanapun, referensi "master" yang baik untuk mencari informasi setelah Anda memiliki PNPDeviceID dari sumber lain.

Apa yang saya temukan adalah cara terbaik untuk menghitung perangkat USB adalah dengan menanyakannya Win32_USBControllerDevice. Meskipun tidak memberikan informasi terperinci untuk perangkat, itu benar-benar menghitung perangkat USB Anda dan memberi Anda pasangan Anteseden / Tergantung PNPDeviceIDuntuk setiap Perangkat USB (termasuk Hub, perangkat non-Hub, dan perangkat yang kompatibel dengan HID) pada perangkat Anda. sistem. Setiap Dependen yang dikembalikan dari kueri akan menjadi Perangkat USB. Anteseden akan menjadi Pengontrol yang ditetapkan, salah satu Pengontrol USB yang dikembalikan dengan melakukan kueri Win32_USBController.

Sebagai bonus, tampak bahwa di bawah tenda, WMI berjalan di Pohon Perangkat saat menanggapi Win32_USBControllerDevicekueri, sehingga urutan hasil ini dikembalikan dapat membantu mengidentifikasi hubungan induk / anak. (Ini tidak didokumentasikan dan karenanya hanya tebakan; gunakan CM_Get_Parent (atau Child + Sibling ) SetupDi API untuk hasil yang pasti.) Sebagai opsi untuk SetupDi API, tampaknya untuk semua perangkat yang terdaftar di bawahnya Win32_USBHubdapat dicari di registri (at HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\ + PNPDeviceID) dan akan memiliki parameter ParentIdPrefixyang akan menjadi awalan bidang terakhir di PNPDeviceID anak-anaknya, jadi ini juga bisa digunakan dalam pertandingan karakter pengganti untuk memfilter Win32_PnPEntitykueri.

Dalam lamaran saya, saya melakukan hal berikut:

  • (Opsional) Mengkueri Win32_PnPEntitydan menyimpan hasil dalam peta nilai kunci (dengan PNPDeviceID sebagai kunci) untuk pengambilan nanti. Ini opsional jika Anda ingin melakukan kueri individual nanti.
  • Ditanyakan Win32_USBControllerDeviceuntuk daftar definitif perangkat USB di sistem saya (semua Dependen) dan mengekstrak PNPDeviceIDs ini. Saya melangkah lebih jauh, berdasarkan urutan mengikuti pohon perangkat, untuk menetapkan perangkat ke hub akar (perangkat pertama dikembalikan, bukan pengontrol) dan membangun pohon berdasarkan parentIdPrefix. Urutan yang dikembalikan kueri, yang cocok dengan enumerasi pohon perangkat melalui SetupDi, adalah masing-masing hub root (untuk siapa Anteseden mengidentifikasi pengontrol), diikuti dengan iterasi perangkat di bawahnya, misalnya, di sistem saya:
    • Hub root pengontrol pertama
    • Hub root pengontrol kedua
      • Hub pertama di bawah hub root dari pengontrol kedua (memiliki parentIdPrefix)
        • Perangkat komposit pertama di bawah hub pertama di bawah hub akar pengontrol kedua (PNPDeviceID cocok di atas ParentIdPrefix hub; memiliki ParentIdPrefix sendiri)
          • Bagian Perangkat HID dari perangkat komposit (PNPDeviceID cocok di atas ParentIDPrefix perangkat komposit)
        • Perangkat kedua di bawah hub pertama di bawah hub akar pengontrol kedua
          • Perangkat HID bagian dari perangkat komposit
      • Hub kedua di bawah hub akar pengontrol kedua
        • Perangkat pertama di bawah hub kedua di bawah hub akar pengontrol kedua
      • Hub ketiga di bawah hub akar pengontrol kedua
      • dll.
  • Ditanyakan Win32_USBController. Ini memberi saya informasi rinci tentang PNPDeviceIDs dari pengontrol saya yang ada di bagian atas pohon perangkat (yang merupakan Anteseden dari kueri sebelumnya). Menggunakan pohon yang diturunkan pada langkah sebelumnya, secara rekursif melakukan iterasi terhadap turunannya (hub root) dan turunannya (hub lain) dan turunannya (perangkat non-hub dan perangkat komposit) dan turunannya, dll.
    • Detail yang diambil untuk setiap perangkat di pohon saya dengan merujuk peta yang disimpan di langkah pertama. (Secara opsional, seseorang dapat melewati langkah pertama, dan melakukan kueri satu Win32_PnPEntityper satu menggunakan PNPDeviceId untuk mendapatkan informasi pada langkah ini; mungkin tradeoff cpu vs. memori menentukan urutan mana yang lebih baik.)

Singkatnya, Win32USBControllerDeviceDependen adalah daftar lengkap Perangkat USB pada sistem (selain Pengontrol itu sendiri, yang merupakan Anteseden dalam kueri yang sama), dan dengan mereferensikan PNPDeviceIdpasangan ini dengan informasi dari registri dan dari kueri lain yang disebutkan, gambaran rinci dapat dibuat.

Daniel Widdis
sumber
Jika seseorang memiliki 4 pemindai identik yang terhubung, bagaimana Anda membedakan mana yang jika digunakan pada 4 operasi berbeda, misalnya?
topshot
2
@topshot PNPDeviceID unik selama terhubung. Tidak akan ada cara untuk mengetahui apakah Anda memutuskan satu dan menghubungkan yang kedua identik nanti. ID ini juga menjadi referensi silang di area lain untuk mengidentifikasi operasi mana yang digunakan.
Daniel Widdis
3
Jika perangkat memiliki nomor seri built-in, maka perangkat dapat dibedakan (itulah tujuan dari nomor seri). Nomor seri digunakan sebagai "ID instance" PnP. Jika perangkat tidak berisi nomor seri, maka ID instance pada dasarnya adalah jalur melalui pohon perangkat dari root ke perangkat (dan berisi karakter '&')
Brian
Sebagai fallback, selalu ada mengamati daftar perangkat dan mencabut dan memasang kembali sambil mengamati perubahan.
Penggila teknologi
14

Untuk melihat device yang saya minati, saya telah menggantinya Win32_USBHubdengan Win32_PnPEntitykode Adel Hazzah, berdasarkan postingan ini . Ini bekerja untuk saya:

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; }
  }
}
ocroquette.dll
sumber
Ini bekerja dengan baik. Untuk mempermudah dalam menentukan perangkat mana yang baru saja Anda sambungkan, tulis untuk berjalan dalam interval, tulis entri ke kamus, dan laporkan penambahan apa pun dari terakhir kali Anda menjalankannya.
nixkuroi
8

Adel Hazzah ini jawaban memberi kode bekerja, Daniel Widdis ini dan Nedko ini komentar menyebutkan bahwa Anda perlu query Win32_USBControllerDevice dan menggunakan properti Dependent nya, dan Daniel jawaban memberikan banyak detail tanpa kode.

Berikut adalah sintesis dari pembahasan di atas untuk memberikan kode kerja yang mencantumkan properti perangkat PNP yang dapat diakses langsung dari semua perangkat USB yang terhubung:

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

    }

}

Anda harus menambahkan penanganan pengecualian jika Anda menginginkannya. Konsultasikan jawaban Daniel jika Anda ingin mengetahui pohon perangkat dan semacamnya.

Tydaeus
sumber
5

Ini adalah contoh yang jauh lebih sederhana untuk orang yang hanya mencari drive usb yang dapat dilepas.

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
sumber
2
Akan mengembalikan floppy juga, mungkin pembaca kartu USB, kemungkinan drive Zip, Jazz, & Orb
Mad Myche
Ini adalah solusi ideal untuk orang yang hanya ingin mencocokkan nama ramah USB. Saya menggunakan contoh ini untuk backup data dan karena perubahan huruf drive saya perlu mencari nama (di sini drive.VolumeLabel)
Bio42
4

Jika Anda mengubah ManagementObjectSearcher sebagai berikut:

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

Jadi "GetUSBDevices () terlihat seperti ini"

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

}

Hasil Anda akan terbatas pada perangkat USB (berbeda dengan semua jenis di sistem Anda)

Russell Gantman
sumber
1
Klausa where mencari deviceID yang dimulai dengan USB kehilangan beberapa item. Lebih baik mengulang Dependen "Win32_USBControllerDevice"
Daniel Widdis
2

Anda mungkin menemukan utas ini berguna. Dan inilah proyek kode google yang mencontohkan ini (P / Memanggil ke setupapi.dll).

Darin Dimitrov
sumber
Apakah Anda tahu mengapa kelas ObjectQuery tidak memiliki referensi meskipun saya menggunakan System.Management?
Robert
@Robert sudahkah Anda menambahkan referensi ke proyek? Anda dapat melakukan ini dengan mengklik kanan Referensi dalam proyek Anda> Tambahkan Referensi ...> Cari dan periksa 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
sumber
apa fungsinya object value?
newbieguy
Ikuti tur properti lain yang tersedia pada disk, dan simpan nilainya dalam nilai objek
JxDarkAngel