연결된 USB 장치 목록 가져 오기


93

Windows 컴퓨터에 연결된 모든 USB 장치 목록을 얻으려면 어떻게해야합니까?

답변:


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 스틱의 속성으로 이동하면 "Kingston DataTraveler 2.0 USB 장치"가 표시됩니다.
Robert

2
DeviceID와 PNPDeviceID의 차이점은 무엇입니까?
Shimmy Weitzhandler

1
위의 프로그램을 실행하면 USB 하드 디스크, 키보드 및 마우스를 얻었지만 USB 카메라, USB A / D는 얻지 못합니다. 모든 USB 장치가 표시되지 않는 이유는 무엇입니까?
Curt

8
모든 USB 장치의 목록을 수신하려면 "Win32_USBHub"가 아니라 "Win32_USBControllerDevice"를 쿼리해야합니다. 그런 다음 "Dependent"속성을 사용하여 장치 주소 문자열을 가져옵니다.
Nedko 2013

1
이 검색에는 8 초가 걸립니다. 물건을 고정 할 가능성이 있습니까?
다니엘

44

나는 이전 질문에 답하고 있다는 것을 알고 있지만,이 같은 연습을 통해 조금 더 많은 정보를 찾았습니다. 토론에 많은 기여를 할 것이며이 질문을 발견하고이 질문을 찾는 다른 사람을 도울 것입니다. 기존 답변이 부족합니다.

허용 대답은 가까이, 그리고 사용하여 수정 될 수 Nedko의 의견 그것입니다. 관련된 WMI 클래스에 대한 자세한 이해는 그림을 완성하는 데 도움이됩니다.

Win32_USBHubUSB 허브 만 반환합니다 . 돌이켜 보면 명백해 보이지만 위의 논의는 그것을 놓친다. 여기에는 가능한 모든 USB 장치가 포함되지 않고 추가 장치의 허브 역할을 할 수있는 (적어도 이론 상으로는) USB 장치 만 포함됩니다. 허브가 아닌 일부 장치 (특히 복합 장치의 일부)가 누락됩니다.

Win32_PnPEntity모든 USB 장치와 수백 개의 비 USB 장치가 포함됩니다. 목록을 필터링하기 위해 "USB %"로 시작하는 DeviceID에 대한 WHERE 절 검색을 사용 하라는 Russel Gantman의 조언 Win32_PnPEntity은 유용하지만 약간 불완전합니다. 블루투스 장치, 일부 프린터 / 인쇄 서버, HID 호환 마우스 및 키보드가 누락되었습니다. "USB \ %", "USBSTOR \ %", "USBPRINT \ %", "BTH \ %", "SWD \ %"및 "HID \ %"를 보았습니다. Win32_PnPEntity그러나 다른 소스에서 PNPDeviceID를 소유하게되면 정보를 조회하기위한 좋은 "마스터"참조입니다.

내가 찾은 것은 USB 장치를 열거하는 가장 좋은 방법은 쿼리하는 것 Win32_USBControllerDevice입니다. 장치에 대한 자세한 정보는 제공하지 않지만 USB 장치를 완전히 열거 PNPDeviceID하고 모든 USB 장치 (허브, 비 허브 장치 및 HID 호환 장치 포함)에 대한 선행 / 종속 쌍 을 제공합니다. 체계. 쿼리에서 반환 된 각 종속 항목은 USB 장치입니다. Antecedent는 쿼리에 의해 반환 된 USB 컨트롤러 중 하나 인 컨트롤러가 할당됩니다 Win32_USBController.

보너스로 WMI 는 쿼리에 응답 할 때 장치 트리Win32_USBControllerDevice 를 탐색하므로 이러한 결과가 반환되는 순서는 상위 / 하위 관계를 식별하는 데 도움이 될 수 있습니다. (이것은 문서화되지 않았으므로 추측 일뿐 입니다. 확실한 결과를 얻으 려면 SetupDi API의 CM_Get_Parent (또는 Child + Sibling )를 사용하십시오.) SetupDi API에 대한 옵션으로 아래에 나열된 모든 장치에 대해 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. 이것은 장치 트리의 맨 위에있는 컨트롤러의 PNPDeviceID에 대한 자세한 정보를 제공했습니다 (이전 쿼리의 선행 항목). 이전 단계에서 파생 된 트리를 사용하여 하위 (루트 허브)와 하위 (다른 허브) 및 하위 (허브가 아닌 장치 및 복합 장치) 및 하위 등을 반복적으로 반복했습니다.
    • 첫 번째 단계에서 저장된 맵을 참조하여 내 트리의 각 장치에 대한 세부 정보를 검색했습니다. (선택적으로 첫 번째 단계를 건너 Win32_PnPEntity뛰고이 단계에서 정보를 얻기 위해 PNPDeviceId를 사용하여 개별적으로 쿼리 할 수 있습니다. 어느 순서가 더 나은지 결정하는 CPU 대 메모리 절충안 일 것입니다.)

요약하면 Win32USBControllerDeviceDependents는 시스템에있는 USB 장치의 전체 목록이며 (컨트롤러 자체는 제외하고, 동일한 쿼리에서 선행 항목 임) PNPDeviceId레지스트리 및 언급 된 다른 쿼리의 정보와 이러한 쌍을 상호 참조하여 상세한 그림을 구성 할 수 있습니다.


하나에 4 개의 동일한 스캐너가 연결되어있는 경우, 예를 들어 4 개의 다른 작업에 사용 된 경우 어떤 스캐너를 구별 할 수 있습니까?
topshot

2
@topshot PNPDeviceID는 연결되어있는 한 고유합니다. 하나의 연결을 끊고 나중에 동일한 두 번째를 연결했는지 알 수있는 방법이 없습니다. 이 ID는 사용되는 작업을 식별하기 위해 다른 영역에서도 상호 참조됩니다.
Daniel Widdis

3
장치에 일련 번호가 내장되어 있으면 장치를 구별 할 수 있습니다 (즉, 일련 번호의 목적). 일련 번호는 PnP "인스턴스 ID"로 사용됩니다. 장치에 일련 번호가없는 경우 인스턴스 ID는 기본적으로 장치 트리를 통해 루트에서 장치로의 경로입니다 ( '&'문자 포함)
Brian

대체로 항상 장치 목록을 관찰하고 변경 사항을 확인하는 동안 플러그를 뽑았다가 다시 연결합니다.
Technophile

14

관심이있는 장치를보기 위해이 게시물을 기반으로 Adel Hazzah의 코드에서로 교체 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

8

Adel Hazzah의 답변 은 작동 코드를 제공하고 Daniel WiddisNedko의 의견은 Win32_USBControllerDevice를 쿼리하고 해당 Dependent 속성을 사용해야한다고 언급하며 Daniel의 답변 은 코드없이 많은 세부 정보를 제공합니다.

다음은 연결된 모든 USB 장치의 직접 액세스 할 수있는 PNP 장치 속성을 나열하는 작업 코드를 제공하기 위해 위의 논의를 종합 한 것입니다.

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 카드 리더, 가능한 우편, 재즈, 오브 드라이브 플로피를 반환합니다
미친 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로 시작하는 deviceID를 검색하는 where 절에서 일부 항목이 누락되었습니다. "Win32_USBControllerDevice"의 종속 항목을 반복하는 것이 좋습니다
Daniel Widdis

2

이 스레드가 유용 할 수 있습니다 . 그리고 이것을 예시 하는 구글 코드 프로젝트가 있습니다 (P / Invokes into setupapi.dll).


System.Management를 사용하고 있는데도 ObjectQuery 클래스에 참조가없는 이유를 알고 있습니까?
Robert

@Robert 프로젝트에 대한 참조를 추가 했습니까? 프로젝트에서 참조> 참조 추가 ...> System.Management> 확인을 검색하고 확인하여이를 수행 할 수 있습니다.
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);
                  }
             }
        }
   }

그게 무엇을 object value합니까?
newbieguy

디스크에서 사용 가능한 다른 속성을 둘러보고 그 값을 개체 값에 저장합니다
JxDarkAngel
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.