รับรายชื่ออุปกรณ์ USB ที่เชื่อมต่อ


93

ฉันจะรับรายการอุปกรณ์ USB ที่เชื่อมต่อทั้งหมดบนคอมพิวเตอร์ Windows ได้อย่างไร

คำตอบ:


122

เพิ่มการอ้างอิงถึง 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"
Robert

2
อะไรคือความแตกต่างระหว่าง DeviceID และ PNPDeviceID
Shimmy Weitzhandler

1
เมื่อฉันเรียกใช้โปรแกรมข้างต้นฉันจะได้รับฮาร์ดดิสก์ USB แป้นพิมพ์และเมาส์ แต่ฉันไม่ได้รับกล้อง USB, USB A / D ของฉัน เหตุใดอุปกรณ์ USB ทั้งหมดของฉันจึงไม่ปรากฏขึ้น
Curt

8
ควรสอบถาม "Win32_USBControllerDevice" ไม่ใช่ "Win32_USBHub" เพื่อรับรายชื่ออุปกรณ์ usb ทั้งหมด จากนั้นใช้คุณสมบัติ "ขึ้นอยู่กับ" เพื่อรับสตริงที่อยู่อุปกรณ์
Nedko

1
@ppumkin Win32_USBHubมีเฉพาะฮับ USB ไม่ใช่อุปกรณ์ทั้งหมดดังนั้นคุณจึงไม่มีอุปกรณ์บางอย่าง @nedko ถูกต้องตรงที่คุณต้องได้รับคุณสมบัติ Dependent Win32_USBControllerDeviceเพื่อรับอุปกรณ์ทั้งหมด
Daniel Widdis

45

ฉันรู้ว่าฉันกำลังตอบคำถามเก่า ๆ แต่ฉันเพิ่งทำแบบฝึกหัดเดียวกันนี้และพบข้อมูลเพิ่มเติมอีกเล็กน้อยซึ่งฉันคิดว่าจะมีส่วนช่วยในการอภิปรายและช่วยเหลือคนอื่น ๆ ที่พบคำถามนี้และเห็นว่า คำตอบที่มีอยู่สั้น

คำตอบที่ได้รับการยอมรับอยู่ใกล้และสามารถได้รับการแก้ไขโดยใช้ความคิดเห็น Nedko ของมัน ความเข้าใจโดยละเอียดมากขึ้นเกี่ยวกับคลาส WMI ที่เกี่ยวข้องจะช่วยให้ภาพสมบูรณ์

Win32_USBHubผลตอบแทนเพียง USB ฮับ ดูเหมือนชัดเจนในการมองย้อนกลับไป แต่การอภิปรายข้างต้นพลาดไป ไม่รวมถึงอุปกรณ์ USB ที่เป็นไปได้ทั้งหมดมีเพียงอุปกรณ์ที่สามารถทำหน้าที่เป็นฮับสำหรับอุปกรณ์เพิ่มเติมได้ (ในทางทฤษฎี) ไม่มีอุปกรณ์บางอย่างที่ไม่ใช่ฮับ (โดยเฉพาะบางส่วนของอุปกรณ์คอมโพสิต)

Win32_PnPEntityรวมถึงอุปกรณ์ USB ทั้งหมดและอุปกรณ์อื่น ๆ ที่ไม่ใช่ USB อีกนับร้อย คำแนะนำของ Russel Gantman ในการใช้ WHERE clause Win32_PnPEntityเพื่อค้นหาDeviceID ที่ขึ้นต้นด้วย "USB%" เพื่อกรองรายการมีประโยชน์ แต่ไม่สมบูรณ์เล็กน้อย มันคิดถึงอุปกรณ์บลูทู ธ เครื่องพิมพ์ / เซิร์ฟเวอร์การพิมพ์บางตัวและเมาส์และคีย์บอร์ดที่รองรับ HID ฉันเห็น "USB \%", "USBSTOR \%", "USBPRINT \%", "BTH \%", "SWD \%" และ "HID \%" Win32_PnPEntityอย่างไรก็ตามการอ้างอิง "ต้นแบบ" ที่ดีในการค้นหาข้อมูลเมื่อคุณครอบครอง PNPDeviceID จากแหล่งอื่น

สิ่งที่ผมพบคือวิธีที่ดีที่สุดที่จะระบุอุปกรณ์ USB Win32_USBControllerDeviceคือการแบบสอบถาม แม้ว่าจะไม่ได้ให้ข้อมูลโดยละเอียดสำหรับอุปกรณ์ แต่ก็ระบุอุปกรณ์ USB ของคุณอย่างสมบูรณ์และให้คู่ของก่อนหน้า / ขึ้นPNPDeviceIDอยู่กับอุปกรณ์ USB ทุกเครื่อง (รวมถึงฮับอุปกรณ์ที่ไม่ใช่ฮับและอุปกรณ์ที่รองรับ HID) บนของคุณ ระบบ. ผู้อ้างอิงแต่ละรายการที่ส่งคืนจากแบบสอบถามจะเป็นอุปกรณ์ USB เกิดก่อนจะควบคุมมันได้รับมอบหมายให้เป็นหนึ่งในตัวควบคุม USB Win32_USBControllerที่ส่งกลับโดยการสอบถาม

ในฐานะที่เป็นโบนัสดูเหมือนว่าภายใต้ประทุน WMI จะเดินบนโครงสร้างอุปกรณ์เมื่อตอบสนองต่อWin32_USBControllerDeviceแบบสอบถามดังนั้นลำดับที่ผลลัพธ์เหล่านี้จะถูกส่งกลับสามารถช่วยระบุความสัมพันธ์ของผู้ปกครอง / เด็ก (นี้ไม่ได้มีการบันทึกไว้และจึงมีเพียงการคาดเดา; ใช้ API SetupDi ของCM_Get_Parent (หรือเด็ก + พี่น้อง .) เพื่อให้ได้ผลลัพธ์ที่ชัดเจน) เป็นตัวเลือกให้กับ 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 ของอุปกรณ์คอมโพสิต
      • ฮับที่สองภายใต้ฮับรูทของคอนโทรลเลอร์ตัวที่สอง
        • อุปกรณ์แรกภายใต้ฮับที่สองภายใต้ฮับรูทของคอนโทรลเลอร์ที่สอง
      • ฮับที่สามภายใต้รูทฮับของคอนโทรลเลอร์ตัวที่สอง
      • เป็นต้น
  • Win32_USBControllerสอบถาม สิ่งนี้ให้ข้อมูลโดยละเอียดเกี่ยวกับ PNPDeviceIDs ของคอนโทรลเลอร์ของฉันซึ่งอยู่ที่ด้านบนสุดของโครงสร้างอุปกรณ์ (ซึ่งเป็น Antecedents ของแบบสอบถามก่อนหน้านี้) ใช้ต้นไม้ที่ได้รับในขั้นตอนก่อนหน้านี้วนซ้ำบนลูกของมัน (ฮับราก) และลูกของพวกเขา (ฮับอื่น ๆ ) และลูกของพวกเขา (อุปกรณ์ที่ไม่ใช่ฮับและอุปกรณ์ประกอบ) และลูก ๆ
    • ดึงรายละเอียดสำหรับแต่ละอุปกรณ์ในโครงสร้างของฉันโดยอ้างอิงแผนที่ที่จัดเก็บในขั้นตอนแรก (ทางเลือกหนึ่งอาจข้ามขั้นตอนแรกและสอบถามWin32_PnPEntityทีละรายการโดยใช้ PNPDeviceId เพื่อรับข้อมูลในขั้นตอนนี้อาจเป็น cpu เทียบกับการแลกเปลี่ยนหน่วยความจำเพื่อพิจารณาว่าลำดับใดดีกว่า)

โดยสรุปผู้Win32USBControllerDeviceอยู่ในอุปการะคือรายการอุปกรณ์ USB ทั้งหมดในระบบ (นอกเหนือจากตัวควบคุมเองซึ่งเป็น Antecedents ในแบบสอบถามเดียวกันนั้น) และโดยการอ้างอิงข้ามPNPDeviceIdคู่เหล่านี้ด้วยข้อมูลจากรีจิสทรีและจากการสืบค้นอื่น ๆ ที่กล่าวถึง สามารถสร้างภาพโดยละเอียดได้


หากมีเครื่องสแกนเนอร์ 4 เครื่องที่เชื่อมต่อกันคุณจะแยกแยะได้อย่างไรว่าเครื่องใดถูกใช้ในการทำงานที่ต่างกัน 4 เครื่อง
ท็อปช็อ

2
@topshot PNPDeviceID ไม่ซ้ำกันตราบใดที่มีการเชื่อมต่อ จะไม่มีทางบอกได้ว่าคุณตัดการเชื่อมต่อหรือไม่และเชื่อมต่อครั้งที่สองที่เหมือนกันในภายหลัง รหัสนี้ยังอ้างอิงข้ามในพื้นที่อื่น ๆ เพื่อหวังว่าจะระบุได้ว่าใช้การดำเนินการใด
Daniel Widdis

3
หากอุปกรณ์มีหมายเลขซีเรียลในตัวอุปกรณ์อาจแตกต่างกันได้ (นั่นคือวัตถุประสงค์ของหมายเลขซีเรียล) หมายเลขซีเรียลใช้เป็น "รหัสอินสแตนซ์" ของ PnP หากอุปกรณ์ไม่มีหมายเลขซีเรียล ID อินสแตนซ์จะเป็นเส้นทางผ่านโครงสร้างอุปกรณ์จากรากไปยังอุปกรณ์ (และมีอักขระ '&')
Brian

ในทางเลือกอื่นคุณมักจะสังเกตรายการอุปกรณ์และการถอดปลั๊กและเสียบปลั๊กใหม่ในขณะที่เฝ้าดูการเปลี่ยนแปลง
Technophile

14

หากต้องการดูอุปกรณ์ที่ฉันสนใจฉันได้แทนที่Win32_USBHubด้วยWin32_PnPEntityรหัสของ Adel Hazzah ตามโพสต์นี้ สิ่งนี้ใช้ได้กับฉัน:

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

8

คำตอบของ Adel Hazzah ให้รหัสการทำงานความคิดเห็นของDaniel WiddisและNedkoระบุว่าคุณต้องสอบถาม Win32_USBControllerDevice และใช้คุณสมบัติที่ขึ้นอยู่กับมันและคำตอบของ Daniel ให้รายละเอียดมากมายโดยไม่มีรหัส

นี่คือการสังเคราะห์การสนทนาข้างต้นเพื่อให้รหัสการทำงานที่แสดงรายการคุณสมบัติอุปกรณ์ 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;
        }

    }

}

คุณจะต้องเพิ่มการจัดการข้อยกเว้นหากต้องการ ปรึกษาคำตอบของ Daniel หากคุณต้องการหาโครงสร้างอุปกรณ์และอื่น ๆ


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

4

หากคุณเปลี่ยน 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
ตำแหน่งที่การค้นหารหัสอุปกรณ์ที่เริ่มต้นด้วย USB พลาดบางรายการ เป็นการดีกว่าที่จะย้ำผู้อยู่ในอุปการะของ "Win32_USBControllerDevice"
Daniel Widdis

2

คุณอาจพบว่ากระทู้นี้มีประโยชน์ และนี่คือโครงการรหัสของ Google ที่เป็นตัวอย่างสิ่งนี้ (P / Invokes into setupapi.dll)


คุณมีความคิดหรือไม่ว่าทำไมคลาส ObjectQuery ไม่มีการอ้างอิงแม้ว่าฉันจะใช้ System.Management
Robert

@ Robert คุณได้เพิ่มการอ้างอิงถึงโครงการหรือไม่? คุณสามารถทำได้โดยคลิกขวาที่การอ้างอิงในโครงการของคุณ> เพิ่มการอ้างอิง ... > ค้นหาและตรวจสอบ System.Management> ตกลง
เออร์เนสต์

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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.