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


92

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

回答:


119

プロジェクトの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デバイス」が表示されます。
ロバート

1
DeviceIDとPNPDeviceIDの違いは何ですか?
Shimmy Weitzhandler、2011年

1
上記のプログラムを実行すると、USBハードディスク、キーボード、およびマウスは入手できますが、USBカメラ、USB A / Dは入手できません。USBデバイスがすべて表示されないのはなぜですか?
Curt

8
すべてのUSBデバイスのリストを受信するには、「Win32_USBHub」ではなく「Win32_USBControllerDevice」を照会する必要があります。次に、「依存」プロパティを使用して、デバイスアドレス文字列を取得します。
Nedko 2013

1
この検索には8秒かかります。物事を固定する可能性はありますか?
ダニエル2017年

45

私は古い質問に返信していることはわかっていますが、この同じ演習を行ってもう少し情報を見つけただけです。それは、この議論に大きく貢献し、この質問を見つけてどこにいるのかを見ている人を助けるのに役立つと思います既存の回答では不十分です。

受け入れ答えは近く、使用して修正することができNedkoさんのコメント、それまでに。関連するWMIクラスをより詳細に理解すると、全体像がわかりやすくなります。

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

Win32_PnPEntityすべてのUSBデバイス、および数百の非USBデバイスが含まれます。 「USB%」で始まるDeviceIDのWHERE句検索を使用してリストをフィルタリングするというラッセルガントマンのアドバイスWin32_PnPEntityは役に立ちますが、少し不完全です。Bluetoothデバイス、一部のプリンター/プリントサーバー、HID準拠のマウスとキーボードがありません。「USB \%」、「USBSTOR \%」、「USBPRINT \%」、「BTH \%」、「SWD \%」、「HID \%」を見ました。 Win32_PnPEntityただし、他のソースからのPNPDeviceIDを取得したら、情報を検索するための適切な「マスター」参照です。

私が見つけたのは、USBデバイスを列挙する最良の方法はクエリすることWin32_USBControllerDeviceでした。デバイスの詳細情報は提供しませんが、USBデバイスを完全に列挙し、PNPDeviceIDUSBデバイス(ハブ、ハブ以外のデバイス、HID準拠デバイスを含む)ごとにの先行/従属のペアを提供しますシステム。クエリから返される各DependentはUSBデバイスです。Antecedentは、それが割り当てられているコントローラーであり、クエリによって返されるUSBコントローラーの1つですWin32_USBController

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

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

  • (オプション)Win32_PnPEntity後で検索できるように、結果をクエリして(PNPDeviceIDをキーとして)Key-Valueマップに保存しました。後で個々のクエリを実行する場合、これはオプションです。
  • 照会Win32_USBControllerDevice私のシステム上のUSBデバイスの決定的なリスト(すべての扶養家族)のために、これらのPNPDeviceIDsを抽出しました。デバイスツリーに続く順序に基づいてさらに進んで、デバイスをルートハブ(コントローラーではなく最初に返されるデバイス)に割り当て、parentIdPrefixに基づいてツリーを構築しました。クエリが返す順序は、SetupDiを介したデバイスツリーの列挙と一致し、各ルートハブ(Antecedentがコントローラーを識別する)の後に、その下にあるデバイス(例:システム)の反復が続きます。
    • 最初のコントローラーのルートハブ
    • 2番目のコントローラーのルートハブ
      • 2番目のコントローラーのルートハブの下にある最初のハブ(parentIdPrefixあり)
        • 2番目のコントローラーのルートハブの下の最初のハブの下にある最初の複合デバイス(PNPDeviceIDはハブのParentIdPrefixの上に一致し、独自のParentIdPrefixを持っています)
          • 複合デバイスのHIDデバイス部分(PNPDeviceIDは複合デバイスのParentIDPrefixと一致します)
        • 2番目のコントローラーのルートハブの下の最初のハブの下にある2番目のデバイス
          • 複合デバイスのHIDデバイス部分
      • 2番目のコントローラーのルートハブの下の2番目のハブ
        • 2番目のコントローラーのルートハブの下の2番目のハブの下にある最初のデバイス
      • 2番目のコントローラーのルートハブの下にある3番目のハブ
  • クエリWin32_USBController。これにより、デバイスツリーの最上位にあるコントローラー(前のクエリの前提条件でした)のPNPDeviceIDの詳細情報が得られました。前のステップで派生したツリーを使用して、その子(ルートハブ)とその子(他のハブ)とその子(非ハブデバイスと複合デバイス)とその子などを再帰的に反復しました。
    • 最初のステップで保存されたマップを参照して、ツリー内の各デバイスの詳細を取得しました。(オプションで、最初のステップをスキップWin32_PnPEntityし、PNPDeviceIdを使用して個別にクエリを実行して、このステップで情報を取得できます。おそらく、CPUとメモリのトレードオフで、どちらの順序が適切かを判断します。)

要約すると、Win32USBControllerDeviceDependentsは、システム上のUSBデバイスの完全なリスト(同じクエリ内の前提条件であるコントローラー自体以外)であり、これらのPNPDeviceIdペアをレジストリーや他のクエリからの情報と相互参照することで、詳細な画像を作成できます。


たとえば、4つの同一のスキャナーが接続されている場合、それらが4つの異なる操作で使用された場合、どのスキャナーをどのように区別しましたか?
トップショット2016年

2
@topshot PNPDeviceIDは、接続されている限り一意です。1つを切断して、2番目に同じものを後で接続したかどうかを見分ける方法はありません。このIDは、他の領域でも相互参照され、どの操作が使用されているかを識別できると期待しています。
Daniel Widdis 2016年

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

7

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

    }

}

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


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ドライブも
返却し

これは、USBのフレンドリ名を一致させたいだけの人にとって理想的なソリューションです。私はこの例をデータバックアップに使用し、ドライブ文字が変更されたため、名前(ここではdrive.VolumeLabel)を探す必要があります
Bio42

3

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"のDependentsを反復する方がよい
Daniel Widdis

2

このスレッドが役に立つかもしれません。そして、これを例示するgoogleコードプロジェクトを次に示します(P / Invokes into setupapi.dll)。


System.Managementを使用しているのにObjectQueryクラスに参照がないのはなぜですか?
ロバート

@Robertはプロジェクトへの参照を追加しましたか?これを行うには、プロジェクトで[参照]を右クリックし、[参照の追加...]> [System.Management]を検索して確認し、[OK]をクリックします。
アーネスト、

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.