Nhận danh sách các thiết bị USB được kết nối


92

Làm cách nào để có được danh sách tất cả các thiết bị USB được kết nối trên máy tính windows?

Câu trả lời:


119

Thêm một tham chiếu đến System.Management cho dự án của bạn, sau đó thử một cái gì đó như sau:

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ó cách nào để lấy lại tên thân thiện của thiết bị không? Ví dụ: khi tôi đi vào các thuộc tính của thẻ USB, tôi thấy "Thiết bị USB Kingston DataTraveler 2.0".
Robert

1
Sự khác biệt giữa DeviceID và PNPDeviceID là gì?
Shimmy Weitzhandler

1
Khi tôi chạy chương trình trên, tôi nhận được đĩa cứng USB, bàn phím và chuột, nhưng tôi không nhận được máy ảnh USB, USB A / D của mình. Tại sao tất cả các thiết bị USB của tôi không hiển thị?
Curt

8
nó phải được truy vấn "Win32_USBControllerDevice" chứ không phải "Win32_USBHub" để nhận danh sách tất cả các thiết bị usb. Sau đó sử dụng thuộc tính "Dependent" để lấy chuỗi địa chỉ thiết bị.
Nedko

1
tìm kiếm này mất 8 giây đối với tôi. Có bất kỳ khả năng nào để gắn kết mọi thứ không?
daniel

45

Tôi biết tôi đang trả lời một câu hỏi cũ, nhưng tôi vừa mới xem qua bài tập tương tự này và tìm ra thêm một chút thông tin, mà tôi nghĩ sẽ đóng góp rất nhiều cho cuộc thảo luận và giúp đỡ bất kỳ ai khác tìm thấy câu hỏi này và xem ở đâu các câu trả lời hiện có còn thiếu.

Các câu trả lời được chấp nhận gần, và có thể được sửa chữa bằng comment Nedko của nó. Hiểu biết chi tiết hơn về các Lớp WMI liên quan sẽ giúp hoàn thiện bức tranh.

Win32_USBHubchỉ trả về các Hub USB . Điều đó có vẻ hiển nhiên trong nhận thức muộn màng nhưng cuộc thảo luận ở trên bỏ sót nó. Nó không bao gồm tất cả các thiết bị USB có thể có, chỉ những thiết bị có thể (về lý thuyết, ít nhất) hoạt động như một trung tâm cho các thiết bị bổ sung. Nó bỏ sót một số thiết bị không phải là trung tâm (đặc biệt là các bộ phận của thiết bị hỗn hợp).

Win32_PnPEntitybao gồm tất cả các thiết bị USB và hàng trăm thiết bị không phải USB khác. Lời khuyên của Russel Gantman sử dụng tìm kiếm mệnh đề WHERE Win32_PnPEntitycho DeviceID bắt đầu bằng "USB%" để lọc danh sách là hữu ích nhưng hơi không đầy đủ; nó bỏ sót các thiết bị bluetooth, một số máy in / máy chủ in, chuột và bàn phím tương thích với HID. Tôi đã thấy "USB \%", "USBSTOR \%", "USBPRINT \%", "BTH \%", "SWD \%" và "HID \%". Win32_PnPEntitytuy nhiên, là một tham chiếu "chính" tốt để tra cứu thông tin khi bạn sở hữu PNPDeviceID từ các nguồn khác.

Những gì tôi tìm thấy là cách tốt nhất để liệt kê các thiết bị USB là truy vấn Win32_USBControllerDevice. Mặc dù nó không cung cấp thông tin chi tiết cho các thiết bị, nó hoàn toàn liệt kê các thiết bị USB của bạn và cung cấp cho bạn một cặp Antecedent / Dependent PNPDeviceIDcho mọi Thiết bị USB (bao gồm Hub, thiết bị không phải Hub và thiết bị tương thích với HID) trên hệ thống. Mỗi Người phụ thuộc được trả về từ truy vấn sẽ là một Thiết bị USB. Antecedent sẽ là Bộ điều khiển mà nó được chỉ định, một trong những Bộ điều khiển USB được trả về bằng cách truy vấnWin32_USBController .

Như một phần thưởng, có vẻ như bên dưới, WMI đi qua Cây thiết bị khi phản hồi Win32_USBControllerDevicetruy vấn, vì vậy thứ tự mà các kết quả này được trả về có thể giúp xác định các mối quan hệ cha / con. (Điều này không được ghi lại và do đó chỉ là phỏng đoán; sử dụng CM_Get_Parent (hoặc Child + Sibling ) của API SetupDi để có kết quả chính xác.) Là một tùy chọn đối với API SetupDi, có vẻ như đối với tất cả các thiết bị được liệt kê trong Win32_USBHubchúng có thể được tra cứu trong sổ đăng ký (at HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\ + PNPDeviceID) và sẽ có một tham số ParentIdPrefixsẽ là tiền tố của trường cuối cùng trong PNPDeviceID của trường con của nó, vì vậy, điều này cũng có thể được sử dụng trong một đối sánh ký tự đại diện để lọcWin32_PnPEntity truy vấn.

Trong ứng dụng của tôi, tôi đã làm như sau:

  • (Tùy chọn) Đã hỏi Win32_PnPEntity và lưu trữ kết quả trong bản đồ khóa-giá trị (với PNPDeviceID làm khóa) để truy xuất sau này. Đây là tùy chọn nếu bạn muốn thực hiện các truy vấn riêng lẻ sau này.
  • Đã truy vấn Win32_USBControllerDevicedanh sách chính xác các thiết bị USB trên hệ thống của tôi (tất cả các Thiết bị phụ thuộc) và trích xuất PNPDeviceID của những thiết bị này. Tôi đã đi xa hơn, dựa trên thứ tự theo sau cây thiết bị, để gán các thiết bị cho trung tâm gốc (thiết bị đầu tiên được trả về, chứ không phải bộ điều khiển) và xây dựng một cây dựa trên parentIdPrefix. Thứ tự mà truy vấn trả về, khớp với kiểu liệt kê cây thiết bị qua SetupDi, là mỗi trung tâm gốc (mà Antecedent xác định bộ điều khiển), theo sau là một lần lặp lại các thiết bị dưới nó, ví dụ: trên hệ thống của tôi:
    • Trung tâm gốc của bộ điều khiển đầu tiên
    • Trung tâm gốc của bộ điều khiển thứ hai
      • Trung tâm đầu tiên dưới trung tâm gốc của bộ điều khiển thứ hai (có parentIdPrefix)
        • Thiết bị tổng hợp đầu tiên dưới trung tâm đầu tiên dưới trung tâm gốc của bộ điều khiển thứ hai (PNPDeviceID khớp với ParentIdPrefix của trung tâm; có ParentIdPrefix của riêng nó)
          • Phần thiết bị HID của thiết bị hỗn hợp (PNPDeviceID khớp với ParentIDPrefix của thiết bị tổng hợp)
        • Thiết bị thứ hai dưới trung tâm thứ nhất dưới trung tâm gốc của bộ điều khiển thứ hai
          • Thiết bị HID một phần của thiết bị tổng hợp
      • Trung tâm thứ hai dưới trung tâm gốc của bộ điều khiển thứ hai
        • Thiết bị đầu tiên dưới trung tâm thứ hai dưới trung tâm gốc của bộ điều khiển thứ hai
      • Trung tâm thứ ba dưới trung tâm gốc của bộ điều khiển thứ hai
      • Vân vân.
  • Chất vấn Win32_USBController . Điều này đã cung cấp cho tôi thông tin chi tiết về PNPDeviceIDs của bộ điều khiển của tôi nằm ở đầu cây thiết bị (là Antecedents của truy vấn trước đó). Sử dụng cây có nguồn gốc ở bước trước, lặp lại đệ quy trên các cây con của nó (các trung tâm gốc) và các con của chúng (các trung tâm khác) và các con của chúng (thiết bị không phải trung tâm và thiết bị hỗn hợp) và con của chúng, v.v.
    • Đã truy xuất chi tiết cho từng thiết bị trong cây của tôi bằng cách tham chiếu bản đồ được lưu trữ trong bước đầu tiên. (Theo tùy chọn, người ta có thể bỏ qua bước đầu tiên và truy vấn Win32_PnPEntityriêng lẻ bằng PNPDeviceId để lấy thông tin ở bước này; có thể là sự cân bằng giữa cpu so với bộ nhớ để xác định thứ tự nào tốt hơn.)

Tóm lại, Win32USBControllerDeviceNgười phụ thuộc là một danh sách đầy đủ các Thiết bị USB trên một hệ thống (không phải chính Bộ điều khiển, là Bộ điều khiển trong cùng một truy vấn) và bằng cách tham chiếu chéo các PNPDeviceIdcặp này với thông tin từ sổ đăng ký và từ các truy vấn khác được đề cập, một hình ảnh chi tiết có thể được xây dựng.


Nếu một máy có 4 máy quét giống nhau được kết nối, làm thế nào bạn có thể phân biệt được máy quét nào nếu chúng được sử dụng ở 4 hoạt động khác nhau, chẳng hạn?
Tophot

2
@topshot PNPDeviceID là duy nhất miễn là nó được kết nối. Sẽ không có cách nào để biết liệu bạn đã ngắt kết nối một thiết bị và kết nối một thiết bị thứ hai giống hệt nhau sau đó hay không. ID này cũng được tham chiếu chéo trong các lĩnh vực khác để hy vọng xác định được thao tác nào được sử dụng.
Daniel Widdis

3
Nếu các thiết bị có số sê-ri tích hợp, thì các thiết bị có thể được phân biệt (đó là mục đích của số sê-ri). Số sê-ri được sử dụng làm "ID phiên bản" PnP. Nếu thiết bị không chứa một số sê-ri, sau đó ID dụ về cơ bản là con đường qua cây thiết bị từ gốc đến thiết bị (và chứa '&' ký tự)
Brian

Để dự phòng, luôn có quan sát danh sách các thiết bị và rút và cắm lại trong khi theo dõi các thay đổi.
Technophile

14

Để xem các thiết bị tôi quan tâm, tôi đã thay thế Win32_USBHubbằng Win32_PnPEntitymã của Adel Hazzah, dựa trên bài đăng này . Điều này phù hợp với tôi:

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

Điều này làm việc tuyệt vời. Để giúp mọi thứ dễ dàng xác định thiết bị bạn vừa cắm vào, hãy viết thiết bị đó chạy trong một khoảng thời gian, ghi các mục nhập vào từ điển và báo cáo mọi bổ sung từ lần cuối cùng bạn chạy nó.
nixkuroi

7

Câu trả lời của Adel Hazzah đưa ra mã hoạt động, nhận xét của Daniel WiddisNedko đề cập rằng bạn cần truy vấn Win32_USBControllerDevice và sử dụng thuộc tính Dependent của nó, và câu trả lời của Daniel cung cấp rất nhiều chi tiết mà không cần mã.

Dưới đây là tổng hợp cuộc thảo luận ở trên để cung cấp mã làm việc liệt kê các thuộc tính thiết bị PNP có thể truy cập trực tiếp của tất cả các thiết bị USB được kết nối:

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

    }

}

Bạn sẽ cần thêm xử lý ngoại lệ nếu muốn. Tham khảo câu trả lời của Daniel nếu bạn muốn tìm ra cây thiết bị và những thứ tương tự.


5

Đây là một ví dụ đơn giản hơn nhiều cho những người chỉ tìm kiếm ổ USB di động.

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
Sẽ trả về một đĩa mềm là tốt, có thể đọc USB thẻ, có thể Zip, Jazz, và ổ đĩa Orb
Mad Myche

Đây là giải pháp lý tưởng cho những người chỉ muốn phù hợp với tên thân thiện của USB. Tôi sử dụng ví dụ này để sao lưu dữ liệu và kể từ khi ký tự ổ đĩa thay đổi tôi cần phải tìm tên (ở đây drive.VolumeLabel)
Bio42

3

Nếu bạn thay đổi ManagementObjectSearcher thành như sau:

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

Vì vậy, "GetUSBDevices () trông giống như thế này"

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

}

Kết quả của bạn sẽ bị giới hạn ở các thiết bị USB (trái ngược với tất cả các loại trên hệ thống của bạn)


1
Mệnh đề where tìm kiếm ID thiết bị bắt đầu bằng USB bỏ sót một số mục. Tốt hơn nên lặp lại phần Phụ thuộc của "Win32_USBControllerDevice"
Daniel Widdis

2

Bạn có thể thấy chủ đề này hữu ích. Và đây là một dự án mã của google minh chứng cho điều này (nó P / Gọi vào setupapi.dll).


Bạn có biết tại sao lớp ObjectQuery không có tham chiếu mặc dù tôi đang sử dụng System.Management không?
Robert

@Robert bạn đã thêm tham chiếu vào dự án chưa? Bạn có thể thực hiện việc này bằng cách nhấp chuột phải vào Tài liệu tham khảo trong dự án của bạn> Thêm tài liệu tham khảo ...> Tìm kiếm và kiểm tra 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);
                  }
             }
        }
   }

cái đó object valuelàm gì
newbieguy

Tham quan các thuộc tính có sẵn khác trên đĩa và lưu giá trị của nó trong giá trị đối tượng
JxDarkAngel
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.