none
USBメモリのシリアル番号を得るべく WMIを利用しよとしていますが、上手く行きません。 RRS feed

  • 質問

  • ネット上で WMI Code Creator v1.0 で生成したコードがありましたので、

    ManagementObjectSearcher searcher = new ManagementObjectSearcher("root\\CIMV2", "SELECT * FROM Win32_USBController");          foreach (ManagementObject queryObj in searcher.Get()) { Console.WriteLine("Win32_USBController instance");

        Console.WriteLine("DeviceID: {0}", queryObj["DeviceID"]); }

    これを使っていますが、USBを装着してもしていなくても、ある同じ値しか得られません。
    内部のUSBのControllerかの値なのでしょうか。デバイスマネージャで得られる値と違います。

    デバイスマネージャのUSB 大容量記憶装置 の方は 
    USBメモリを装着した時にあらわれ、また違うUSBメモリを刺したら違う値になります。
    この値をプログラムで得たいのですが、どうしたら良いですか?



    mnicksashimisan

    2020年6月23日 6:23

回答

  • 私のレベルでは何を言われているのかよく分からないのですが、
    WMI Code Creator v1.0 を動かし、
    Classes           に Win32_USBControllerDevice
    Select the properties you want values for. に Dependent 
    を指定したら下記のコードを吐き出し、求める値が得られました。
    ありがとうございました。

    using System;
    using System.Management;
    using System.Windows.Forms;
    
    namespace WMISample
    {
        public class MyWMIQuery
        {
            public static void Main()
            {
                try
                {
                    ManagementObjectSearcher searcher = 
                        new ManagementObjectSearcher("root\\CIMV2", 
                        "SELECT * FROM Win32_USBControllerDevice"); 
    
                    foreach (ManagementObject queryObj in searcher.Get())
                    {
                        Console.WriteLine("-----------------------------------");
                        Console.WriteLine("Win32_USBControllerDevice instance");
                        Console.WriteLine("-----------------------------------");
                        Console.WriteLine("Dependent: {0}", queryObj["Dependent"]);
                    }
                }
                catch (ManagementException e)
                {
                    MessageBox.Show("An error occurred while querying for WMI data: " + e.Message);
                }
            }
        }
    }


    mnicksashimisan

    2020年6月24日 6:31
  • foreach (ManagementObject queryObj in searcher.Get())
    {
        Console.WriteLine("-----------------------------------");
        Console.WriteLine("Win32_USBControllerDevice instance");
        Console.WriteLine("-----------------------------------");
        Console.WriteLine("Dependent: {0}", queryObj["Dependent"]);
    }
    

    Win32_USBControllerDevice クラスの Dependent プロパティは、CIM_LogicalDevice クラスへの参照情報を意味する文字列です。

    そしてその参照を辿ることで、接続されている機器のより詳しい情報を得ることができます。たとえばそれが、USB 接続されたディスク装置なのか、あるいはマウスであるのかといった事を調べるために使うことができます。

    以下、その参照を辿って表示するサンプルです。

    USB 機器を列挙する Win32_USBControllerDevice 版に加えて、プラグ & プレイ機器を列挙する Win32_PnPDevice 版も載せてみました。

    static void Main()
    {
        // Win32_USBControllerDevice から辿る場合
        var searcher = new ManagementObjectSearcher("SELECT * FROM Win32_USBControllerDevice");
        foreach (ManagementObject queryObj in searcher.Get())
        {
            // CIM_USBController またはその派生クラス (Win32_USBController)
            var antecedent = (string)queryObj["Antecedent"];
            var controller = new ManagementObject(new ManagementPath(antecedent));
            Console.WriteLine("Antecedent: {0}", antecedent);
            Console.WriteLine("├  (ClassName): {0}", controller.ClassPath.ClassName);
            Console.WriteLine("├     DeviceID: {0}", controller["DeviceID"]);
            Console.WriteLine("├  PNPDeviceID: {0}", controller["PNPDeviceID"]);
            Console.WriteLine("├         Name: {0}", controller["Name"]);
            Console.WriteLine("├      Caption: {0}", controller["Caption"]);
            Console.WriteLine("├  Description: {0}", controller["Description"]);
            Console.WriteLine("├ Manufacturer: {0}", controller["Manufacturer"]);
            Console.WriteLine("└  InstallDate: {0}", controller["InstallDate"]);
    
            // CIM_LogicalDevice またはその派生クラス (Win32_PnPEntity)
            var dependent = (string)queryObj["Dependent"];
            var device = new ManagementObject(new ManagementPath(dependent));
            Console.WriteLine("Dependent: {0}", dependent);
            Console.WriteLine("├  (ClassName): {0}", device.ClassPath.ClassName);
            Console.WriteLine("├     DeviceID: {0}", device["DeviceID"]);
          //Console.WriteLine("├   HardwareID: {0}", string.Join(",", device["HardwareID"] as string[] ?? new string[0]));
          //Console.WriteLine("├ CompatibleID: {0}", string.Join(",", device["CompatibleID"] as string[] ?? new string[0]));
          //Console.WriteLine("├     PNPClass: {0}", device["PNPClass"]);
            Console.WriteLine("├         Name: {0}", device["Name"]);
            Console.WriteLine("├      Caption: {0}", device["Caption"]);
            Console.WriteLine("├  Description: {0}", device["Description"]);
          //Console.WriteLine("├ Manufacturer: {0}", device["Manufacturer"]);
            Console.WriteLine("└  InstallDate: {0}", device["InstallDate"]);
            Console.WriteLine();
        }
    
    
        // Enter キーで次へ
        Console.ReadKey();
        Console.Clear();
    
    
        // Win32_PnPDevice から辿る場合
        searcher = new ManagementObjectSearcher("SELECT * FROM Win32_PnPDevice");
        foreach (ManagementObject queryObj in searcher.Get())
        {
            // CIM_LogicalDevice またはその派生クラス(Win32_DiskDrive, Win32_PointingDevice, Win32_Keyboard, Win32_SoundDevice, Win32_SCSIController, Win32_USBController, Win32_USBHub, ...)
            var sameElement = (string)queryObj["SameElement"];
            var device = new ManagementObject(new ManagementPath(sameElement));
            Console.WriteLine("Dependent: {0}", sameElement);
            Console.WriteLine("├  (ClassName): {0}", device.ClassPath.ClassName);
            Console.WriteLine("├     DeviceID: {0}", device["DeviceID"]);
            Console.WriteLine("├         Name: {0}", device["Name"]);
            Console.WriteLine("├      Caption: {0}", device["Caption"]);
            Console.WriteLine("├  Description: {0}", device["Description"]);
            Console.WriteLine("└  InstallDate: {0}", device["InstallDate"]);
    
            // Win32_PnPEntity またはその派生クラス
            var systemElement = (string)queryObj["SystemElement"];
            var entitiy = new ManagementObject(new ManagementPath(systemElement));
            Console.WriteLine("Dependent: {0}", systemElement);
            Console.WriteLine("├    ClassName: {0}", entitiy.ClassPath.ClassName);
            Console.WriteLine("├     DeviceID: {0}", entitiy["DeviceID"]);
            Console.WriteLine("├         Name: {0}", entitiy["Name"]);
            Console.WriteLine("├      Caption: {0}", entitiy["Caption"]);
            Console.WriteLine("├  Description: {0}", entitiy["Description"]);
            Console.WriteLine("├ Manufacturer: {0}", entitiy["Manufacturer"]);
            Console.WriteLine("└  InstallDate: {0}", entitiy["InstallDate"]);
    
            Console.WriteLine();
        }
        Console.ReadKey();
    }
    2020年6月24日 12:04

すべての返信

  • Win32_USBController は文字通り、USB ホストコントローラーを表すものですね。
    PowerShell で 『Get-WmiObject Win32_USBController』を実行してみるのが分かりやすいかと。

    必要なのは Win32_USBController ではなく、Win32_USBControllerDevice および Win32_PnPEntity では無いでしょうか。
    PowerShell だと『Get-WmiObject Win32_USBControllerDevice |%{[wmi]($_.Dependent)} |Sort-Object Manufacturer,Description,DeviceID |Format-Table -GroupBy Manufacturer Description,Service,DeviceID』。

    とりあえず、厳密名クラスジェネレーター (MgmtClassGen.exe) を用いた C# のサンプルを書いてみました。
    WQL だけで処理するなら、ASSOCIATORS OF ステートメント を使えるかも。

    using System;
    using ROOT.CIMV2.Win32;
    class Program
    {
        static void Main()
        {
            var q = from USBControllerDevice device in USBControllerDevice.GetInstances()
                    let pnp = new PnPEntity(device.Dependent)
                    where pnp.PNPClass == "DiskDrive"
                    select pnp;
    
            foreach (var device in q)
            {
                Console.WriteLine(device.Caption);
                Console.WriteLine(device.DeviceID);
                Console.WriteLine();
            }
        }
        Console.ReadKey();
    }
    


    2020年6月23日 10:07
  • error CS0246: 型または名前空間名 'ROOT' が見つかりませんでした。using ディレクティブまたはアセンブリ参照が不足しています。

    というエラーになります。


    mnicksashimisan

    2020年6月24日 1:10
  • 先に述べた通り、そのサンプルは厳密名クラスジェネレーターを用いるものです。

    事前に、 Win32_USBControllerDevice クラスと Win32_PnPEntity クラスの .cs ファイルを MgmtClassGen.exe で生成し、プロジェクトに追加しておいてください。

    Win32_USBControllerDevice の Antecedent プロパティは、USBコントローラー(CIM_USBController の派生クラス) への参照を表し、Dependent プロパティが 論理デバイス(CIM_LogicalDevice の派生クラス)を表します。これらの実際のインスタンスは、Win32_USBController および Win32_PnPEntity になるようです。

    ジェネレーターを使わずに実装したい場合は、最初の質問にあったように、WQL のクエリー文字列(あるいは、RelatedObjectQuery / SelectQuery のインスタンス)を ManagementObjectSearcher に渡す方法で実装してみてください。

    2020年6月24日 4:19
  • 私のレベルでは何を言われているのかよく分からないのですが、
    WMI Code Creator v1.0 を動かし、
    Classes           に Win32_USBControllerDevice
    Select the properties you want values for. に Dependent 
    を指定したら下記のコードを吐き出し、求める値が得られました。
    ありがとうございました。

    using System;
    using System.Management;
    using System.Windows.Forms;
    
    namespace WMISample
    {
        public class MyWMIQuery
        {
            public static void Main()
            {
                try
                {
                    ManagementObjectSearcher searcher = 
                        new ManagementObjectSearcher("root\\CIMV2", 
                        "SELECT * FROM Win32_USBControllerDevice"); 
    
                    foreach (ManagementObject queryObj in searcher.Get())
                    {
                        Console.WriteLine("-----------------------------------");
                        Console.WriteLine("Win32_USBControllerDevice instance");
                        Console.WriteLine("-----------------------------------");
                        Console.WriteLine("Dependent: {0}", queryObj["Dependent"]);
                    }
                }
                catch (ManagementException e)
                {
                    MessageBox.Show("An error occurred while querying for WMI data: " + e.Message);
                }
            }
        }
    }


    mnicksashimisan

    2020年6月24日 6:31
  • 現状のコードだと「USB メモリ」以外(マウスなど)も列挙されてしまいそうですが、構わないのでしょうか?

    Win32_USBControllerDevice.Dependent から得られる論理デバイスの情報を DataGridView に表示するサンプルを書いてみました。

    private void button1_Click(object sender, EventArgs e)
    {
        var q = from ManagementBaseObject usb in new ManagementClass("Win32_USBControllerDevice").GetInstances()
                let dependent = (string)usb["Dependent"]
                let device = new ManagementObject(new ManagementPath(dependent))
                select new
                {
                    Manufacturer = device["Manufacturer"],
                    Name = device["Name"],
                    PNPClass = device["PNPClass"],
                    PNPDeviceID = device["PNPDeviceID"],
                    HardwareID = string.Join("\r\n", (string[])device["HardwareID"])
                };
    
        dataGridView1.DefaultCellStyle.WrapMode = DataGridViewTriState.True;
    
        dataGridView1.DataSource = q.ToList();
    
        dataGridView1.Columns[1].Frozen = true;
        dataGridView1.AutoResizeColumns();
        dataGridView1.AutoResizeRows();
    }
    

    2020年6月24日 10:10
  • 私のレベルでは何を言われているのかよく分からないのですが、

    先の using ROOT.CIMV2.Win32; なコードを試すためには、コマンド プロンプトから

    『MgmtClassGen.exe Win32_USBControllerDevice』
    『MgmtClassGen.exe Win32_PnPEntity』

    のように呼び出して、Win32_USBControllerDevice.cs や Win32_PnPEntity.cs を生成し、このファイルをプロジェクトに追加する必要があります。

    このコマンドライン ツールの使い方は、『MgmtClassGen.exe /?』で調べられます。
    パラメーター指定を変えれば、VB 向けのコードも生成できます

    厳密型クラスジェネレーター (MgmtClassGen.exe) は、開発環境の一部として、下記のようなパスにインストールされているかと思います。

    • C:\Program Files\Microsoft SDKs\Windows\v6.0A\Bin\mgmtclassgen.exe
    • C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\bin\mgmtclassgen.exe
    • C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\bin\NETFX 4.0 Tools\mgmtclassgen.exe
    • C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.6.1 Tools\mgmtclassgen.exe
    • C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.8 Tools\mgmtclassgen.exe
    2020年6月24日 11:46
  • foreach (ManagementObject queryObj in searcher.Get())
    {
        Console.WriteLine("-----------------------------------");
        Console.WriteLine("Win32_USBControllerDevice instance");
        Console.WriteLine("-----------------------------------");
        Console.WriteLine("Dependent: {0}", queryObj["Dependent"]);
    }
    

    Win32_USBControllerDevice クラスの Dependent プロパティは、CIM_LogicalDevice クラスへの参照情報を意味する文字列です。

    そしてその参照を辿ることで、接続されている機器のより詳しい情報を得ることができます。たとえばそれが、USB 接続されたディスク装置なのか、あるいはマウスであるのかといった事を調べるために使うことができます。

    以下、その参照を辿って表示するサンプルです。

    USB 機器を列挙する Win32_USBControllerDevice 版に加えて、プラグ & プレイ機器を列挙する Win32_PnPDevice 版も載せてみました。

    static void Main()
    {
        // Win32_USBControllerDevice から辿る場合
        var searcher = new ManagementObjectSearcher("SELECT * FROM Win32_USBControllerDevice");
        foreach (ManagementObject queryObj in searcher.Get())
        {
            // CIM_USBController またはその派生クラス (Win32_USBController)
            var antecedent = (string)queryObj["Antecedent"];
            var controller = new ManagementObject(new ManagementPath(antecedent));
            Console.WriteLine("Antecedent: {0}", antecedent);
            Console.WriteLine("├  (ClassName): {0}", controller.ClassPath.ClassName);
            Console.WriteLine("├     DeviceID: {0}", controller["DeviceID"]);
            Console.WriteLine("├  PNPDeviceID: {0}", controller["PNPDeviceID"]);
            Console.WriteLine("├         Name: {0}", controller["Name"]);
            Console.WriteLine("├      Caption: {0}", controller["Caption"]);
            Console.WriteLine("├  Description: {0}", controller["Description"]);
            Console.WriteLine("├ Manufacturer: {0}", controller["Manufacturer"]);
            Console.WriteLine("└  InstallDate: {0}", controller["InstallDate"]);
    
            // CIM_LogicalDevice またはその派生クラス (Win32_PnPEntity)
            var dependent = (string)queryObj["Dependent"];
            var device = new ManagementObject(new ManagementPath(dependent));
            Console.WriteLine("Dependent: {0}", dependent);
            Console.WriteLine("├  (ClassName): {0}", device.ClassPath.ClassName);
            Console.WriteLine("├     DeviceID: {0}", device["DeviceID"]);
          //Console.WriteLine("├   HardwareID: {0}", string.Join(",", device["HardwareID"] as string[] ?? new string[0]));
          //Console.WriteLine("├ CompatibleID: {0}", string.Join(",", device["CompatibleID"] as string[] ?? new string[0]));
          //Console.WriteLine("├     PNPClass: {0}", device["PNPClass"]);
            Console.WriteLine("├         Name: {0}", device["Name"]);
            Console.WriteLine("├      Caption: {0}", device["Caption"]);
            Console.WriteLine("├  Description: {0}", device["Description"]);
          //Console.WriteLine("├ Manufacturer: {0}", device["Manufacturer"]);
            Console.WriteLine("└  InstallDate: {0}", device["InstallDate"]);
            Console.WriteLine();
        }
    
    
        // Enter キーで次へ
        Console.ReadKey();
        Console.Clear();
    
    
        // Win32_PnPDevice から辿る場合
        searcher = new ManagementObjectSearcher("SELECT * FROM Win32_PnPDevice");
        foreach (ManagementObject queryObj in searcher.Get())
        {
            // CIM_LogicalDevice またはその派生クラス(Win32_DiskDrive, Win32_PointingDevice, Win32_Keyboard, Win32_SoundDevice, Win32_SCSIController, Win32_USBController, Win32_USBHub, ...)
            var sameElement = (string)queryObj["SameElement"];
            var device = new ManagementObject(new ManagementPath(sameElement));
            Console.WriteLine("Dependent: {0}", sameElement);
            Console.WriteLine("├  (ClassName): {0}", device.ClassPath.ClassName);
            Console.WriteLine("├     DeviceID: {0}", device["DeviceID"]);
            Console.WriteLine("├         Name: {0}", device["Name"]);
            Console.WriteLine("├      Caption: {0}", device["Caption"]);
            Console.WriteLine("├  Description: {0}", device["Description"]);
            Console.WriteLine("└  InstallDate: {0}", device["InstallDate"]);
    
            // Win32_PnPEntity またはその派生クラス
            var systemElement = (string)queryObj["SystemElement"];
            var entitiy = new ManagementObject(new ManagementPath(systemElement));
            Console.WriteLine("Dependent: {0}", systemElement);
            Console.WriteLine("├    ClassName: {0}", entitiy.ClassPath.ClassName);
            Console.WriteLine("├     DeviceID: {0}", entitiy["DeviceID"]);
            Console.WriteLine("├         Name: {0}", entitiy["Name"]);
            Console.WriteLine("├      Caption: {0}", entitiy["Caption"]);
            Console.WriteLine("├  Description: {0}", entitiy["Description"]);
            Console.WriteLine("├ Manufacturer: {0}", entitiy["Manufacturer"]);
            Console.WriteLine("└  InstallDate: {0}", entitiy["InstallDate"]);
    
            Console.WriteLine();
        }
        Console.ReadKey();
    }
    2020年6月24日 12:04
  • >現状のコードだと「USB メモリ」以外(マウスなど)も列挙されてしまいそうですが、構わないのでしょうか?
    USBの存在さえ分かれば良いので構いません。

    私が提示したコードで得られる値にはPC名なども入っていて、その部分を取り除かなければならず、
    また、VSの出力ペインに得られる文字列には \が2つ続いたり、" があったりで、
    文字列の調整が少し煩いです。

    例示の Win32_USBControllerDevice クラスの参照を辿ることで、
    欲しい部分の情報だけを楽に得ることができるようになりました。
    ありがとうございました。

    その他、色んな情報を取り出す例示もあり、何かの時に利用したいと思います。


    mnicksashimisan

    2020年6月25日 7:58