web-dev-qa-db-ja.com

接続されたUSBデバイスのリストを取得する

Windowsコンピューターに接続されているすべてのUSBデバイスのリストを取得するにはどうすればよいですか?

83
Robert

プロジェクトの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; }
  }
}
105
Adel Hazzah

私は古い質問に答えていることは知っていますが、この同じ演習を行って、もう少し情報を見つけたので、ディスカッションに大きく貢献し、この質問を見つけてどこで既存の答えは不十分です。

受け入れられた答え は近く、 Nedkoのコメント を使用して修正できます。関連するWMIクラスをより詳細に理解することで、全体像を把握できます。

Win32_USBHubはUSBHubsのみを返します。それは後知恵で明らかなようですが、上記の議論はそれを見逃しています。すべての可能なUSBデバイスが含まれているわけではなく、追加のデバイスのハブとして(少なくとも理論的には)動作できるものだけが含まれています。ハブではない一部のデバイス(特に複合デバイスの一部)が欠落しています。

Win32_PnPEntityには、すべてのUSBデバイスと、さらに数百の非USBデバイスが含まれます。 Russel Gantman's WHERE句検索Win32_PnPEntityを使用して、「USB%」で始まるDeviceIDを使用してリストをフィルタリングすることは有用ですが、少し不完全です。 Bluetoothデバイス、一部のプリンター/プリントサーバー、およびHID準拠のマウスとキーボードがありません。 「USB \%」、「USBSTOR \%」、「USBPRINT \%」、「BTH \%」、「SWD \%」、「HID \%」を見ました。ただし、Win32_PnPEntityは、他のソースからPNPDeviceIDを取得したら、情報を検索するための優れた「マスター」リファレンスです。

USBデバイスを列挙する最良の方法は、Win32_USBControllerDeviceを照会することでした。デバイスの詳細情報は提供しませんが、USBデバイスを完全に列挙し、すべてのUSBデバイス(ハブ、非ハブデバイス、およびHID準拠を含む)のPNPDeviceIDsのAntecedent/Dependentペアを提供しますデバイス)。クエリから返される各Dependentは、USBデバイスになります。 Antecedentは、Win32_USBControllerのクエリによって返されるUSBコントローラーの1つである、割り当てられたコントローラーになります。

おまけとして、WMIはWin32_USBControllerDeviceクエリに応答する際に内部的に デバイスツリー を歩くため、これらの結果が返される順序が親/子関係の識別に役立ちます。 (これは文書化されていないため、推測にすぎません。最終的な結果を得るには、SetupDi APIの CM_Get_Parent (または Child + Sibling )を使用してください。)As SetupDi APIのオプションで、Win32_USBHubの下にリストされているすべてのデバイスについて、レジストリで(HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\ + PNPDeviceIDで)検索でき、ParentIdPrefixパラメータがあります。子のPNPDeviceIDの最後のフィールドのプレフィックス。したがって、Win32_PnPEntityクエリをフィルター処理するためにワイルドカード一致で使用することもできます。

私のアプリケーションでは、次のことを行いました。

  • (オプション)Win32_PnPEntityをクエリし、後で取得するためにキー値マップ(PNPDeviceIDをキーとして)に結果を保存しました。後で個別のクエリを実行する場合、これはオプションです。
  • Win32_USBControllerDeviceにシステム上のUSBデバイスの完全なリスト(すべての依存関係)を照会し、これらのPNPDeviceIDを抽出しました。デバイスツリーに続く順序に基づいて、デバイスをルートハブ(コントローラーではなく最初に返されたデバイス)に割り当て、parentIdPrefixに基づいてツリーを構築しました。 SetupDiを介したデバイスツリーの列挙に一致するクエリが返す順序は、各ルートハブ(先行者がコントローラーを識別する相手)であり、その下にデバイスの繰り返しが続きます(例:私のシステム上)。
    • 最初のコントローラーのルートハブ
    • 2番目のコントローラーのルートハブ
      • 2番目のコントローラーのルートハブの下にある最初のハブ(parentIdPrefixがあります)
        • 2番目のコントローラーのルートハブの下にある最初のハブの下にある最初の複合デバイス(PNPDeviceIDはハブのParentIdPrefixに一致し、独自のParentIdPrefixを持っています)
          • 複合デバイスのHIDデバイス部分(PNPDeviceIDは複合デバイスのParentIDPrefixに一致)
        • 2番目のコントローラーのルートハブの下にある最初のハブの下にある2番目のデバイス
          • 複合デバイスのHIDデバイス部分
      • 2番目のコントローラーのルートハブの下の2番目のハブ
        • 2番目のコントローラーのルートハブの下にある2番目のハブの下にある最初のデバイス
      • 2番目のコントローラーのルートハブの下にある3番目のハブ
      • 等.
  • クエリWin32_USBController。これにより、デバイスツリーの最上部にあるコントローラーのPNPDeviceIDの詳細情報が得られました(前のクエリの前件)。前の手順で派生したツリーを使用して、その子(ルートハブ)とその子(他のハブ)およびその子(非ハブデバイスと複合デバイス)およびその子などを再帰的に繰り返します。
    • 最初の手順で保存したマップを参照して、ツリー内の各デバイスの詳細を取得しました。 (オプションで、最初のステップをスキップし、PNPDeviceIdを使用してWin32_PnPEntityを個別にクエリしてこのステップで情報を取得できます。おそらく、CPUとメモリのトレードオフがどちらの順序が良いかを決定します。)

要約すると、Win32USBControllerDevice Dependentsは、システム上のUSBデバイスの完全なリスト(同じクエリの前件であるコントローラー自体を除く)であり、これらのPNPDeviceIdペアを情報と相互参照しますレジストリおよび前述の他のクエリから、詳細な図を作成できます。

34
Daniel Widdis

興味のあるデバイスを見るために、 この投稿 に基づいて、Adel HazzahのコードのWin32_USBHubWin32_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; }
  }
}
12
ocroquette

これは、リムーバブル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));
    }
}
5
Baddack

Adel Hazzahの answer は有効なコードを提供し、 Daniel Widdisの および Nedkoの コメントには、Win32_USBControllerDeviceを照会してそのDependentプロパティを使用する必要があると記載されており、ダニエルの answer コードなしで多くの詳細を提供します。

接続されたすべての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;
        }

    }

}

必要に応じて、例外処理を追加する必要があります。デバイスツリーなどを把握したい場合は、ダニエルの回答を参照してください。

4
Tydaeus

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デバイスに制限されます(システム上のすべてのタイプではありません)

3
Russell Gantman

このスレッド が役に立つかもしれません。そして、これが google code project の例です(P/Invokes into setupapi.dll)。

2
Darin Dimitrov
  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);
                  }
             }
        }
   }
0
JxDarkAngel