宇宙仮面の
C# Programming

 

ImageWMI (Windows Management Instrumentation)

開発環境: Visual Studio 2003 

1.目次

2.目的

WMI は、Windows Management Instrumentation の略で、Windows のシステム管理のためのインターフェースです。
概要説明は、こちらをご覧ください。
これの WMI を使うことにより、サービスがクラッシュしたり、CPU負荷が異常に高くなったときに、管理者にメイル通知する
アプリケーションを開発できます。

中を見ていくとアレッと思うと思いますが、中は通常の Win32 API とはだいぶ違った
インターフェースを持っているのに気がつくと思います。
これは、WMI が WBEM ( Web-based Enterprise Management )イニシアチブと、
DMTF ( Distributed Management Task Force )によって採用された
Common Information Model ( CIM )をベースとしているためです。
DMTF は、コンピュータや、周辺機器等の管理に関する標準を策定する業界団体で、
ノベルやIntel、Cisco、Microsoft、Compaqなどの主要なコンピュータメーカーが参加しています。
代表的なところでは DMI (Desktop Management Interface)の仕様策定を行っています。
これはPCやPCコンポーネントについての情報を定義してアクセスするための標準です。
SNMP(Simple Network Management Protocol) の情報の定義を定めています。

ということで、これを読んだだけでわかったあなたはすごい!

簡単に言えば、コンピュータの管理情報にアクセスするためのインターフェースです。
しかし、侮ることなかれ! コンピュータの管理情報について膨大な情報量が取れます。
おまけに、リモートコンピュータの情報も同様に取れてしまいます。
さらには、リモートコンピュータを再起動するというような、リモートPCのメソッドインボケーションというとんでもない事もできます!

よくできた会社の情報システム部門などで、会社のネットワークを監視するために、SNMPを使った管理が行われていると思いますが、
このWMI は、そのSNMPに提供するのに十分なだけの情報をとることができるはずです。

ということで、正直こんなインターフェースがあるなんて知らなかったので、驚きです。
こんな複雑なインターフェース用意してあって、セキュリティ大丈夫なんだろうかと思ってしまう。

さらに驚きなのは、例によってこれらに関連した情報がほとんどまとまって無いんですよ!
ほんとに読み解くのに苦労しました。
3日間の努力の結果を忘れないようにメモっておきます。
おそらく、一般プログラマーはこんなところまで触らないんでしょうね。

でも、知っておくと、超強力な機能ですよ!知っていて損は無いと思います。

3.参考

(1) http://www.microsoft.com/JAPAN/developer/library/jptech/msdnnews/wmi.htm
(2) http://www.csharphelp.com/archives2/archive334.html
(3) http://www.microsoft.com/japan/msdn/library/default.asp?url=/japan/msdn/library/ja/cpref/html/frlrfSystemManagement.asp
(4) http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wmisdk/wmi/computer_system_hardware_classes.asp

4.ローカルコンピュータの WMI にアクセスする方法

はっきり言って、WMI関連のMS のヘルプのひどさには閉口しました。
WMI を使う方法には、いくつかあって、それぞれ特徴があります。 まずは、ローカルコンピュータにアクセスする場合です。 次に、4つの WMI にアクセスする方法を見てください。
注意
using System.Management; と、System.Management への参照の追加が必要です。
ManagementClass を使って、該当するものをすべて取得する方法。
            ManagementClass managementClass = new ManagementClass("Win32_Service");
            ManagementObjectCollection managementObj = managementClass.GetInstances();
            foreach(ManagementObject mo in managementObj)
                Console.WriteLine(mo["Name"]);
ManagementObjectSearcherを使って、SQL 文で該当するものをすべて取得する方法。
            ManagementObjectSearcher query1 = new ManagementObjectSearcher("SELECT * FROM Win32_Service") ;
            ManagementObjectCollection queryCollection1 = query1.Get();
            foreach( ManagementObject mo in queryCollection1 ) 
                Console.WriteLine(mo["Name"]);
ManagementObjectSearcherを使って、SQL 文で特定の条件のものをすべて取得する方法。
            ManagementObjectSearcher query1 = new ManagementObjectSearcher("SELECT * FROM Win32_Service WHERE State='Stopped'") ;
            ManagementObjectCollection queryCollection1 = query1.Get();
            foreach( ManagementObject mo in queryCollection1 ) 
                Console.WriteLine(mo["Name"]);
ManagementObjectSearcherを使って、SQL 文の SELECT + 項目 により該当する項目だけ取得する方法。
            ObjectQuery query = new ObjectQuery("SELECT Name FROM win32_share");
            ManagementObjectSearcher searcher = new ManagementObjectSearcher( query );
            foreach (ManagementObject share in searcher.Get()) 
            {
                Console.WriteLine("Share = " + share["Name"]);
            }
これらにより、WMI にアクセスすることができます。
これらの中で、"Win32_Service" とか、"SELECT * FROM Win32_Service" の中で "Win32_Service"という文字列が出てきます。
これは、WMI Classes の名前です。 これらの WMI Class は山ほどあります。

まず、おおもとのWMI クラスは、次のようなクラスから構成されています。
クラス説明
WMI System ClassesCommon Information Model (CIM) に基づいたコアとなるクラス
WMI System PropertiesWMI のプロパティのリスト
Win32 Classesroot\cimv2 名前空間のクラス
CIM Classesベーススキーマクラス
Standard Consumer ClassesWMI event consumer
MSFT Classesremote events and policy extension などのオブジェクトを走査するための手段を提供する。
MSMCA ClassesOSに含まれる、システムイベントの操作と記述するための手段を提供する。
WMI C++ ClassesWMI C++クラス
さらに、これらの中で Win32_Classes は、次のように構成されています。
コンピュータの情報でわからないことは無いぐらいの驚くほど山のようなクラスがあります。
Win32_Classes クラスサブクラス
Computer system hardwareCooling device classes
この下にさらに Win32_Fan などがある。
Input device classes
この下にさらに Win32_* がある。
Mass storage classes
この下にさらに Win32_* がある。
Motherboard, controller, and port classes
この下にさらに Win32_* がある。
Networking device classes
この下にさらに Win32_* がある。
Power classes
この下にさらに Win32_* がある。
Printing classes
この下にさらに Win32_* がある。
Telephony classes
この下にさらに Win32_* がある。
Video and monitor classes
この下にさらに Win32_* がある。
Operating systemCOM
この下にさらに Win32_* がある。
Desktop
この下にさらに Win32_* がある。
Drivers
この下にさらに Win32_* がある。
File system
この下にさらに Win32_* がある。
Job objects
この下にさらに Win32_* がある。
Memory and page files
この下にさらに Win32_* がある。
Multimedia audio/visual
この下にさらに Win32_* がある。
Networking
この下にさらに Win32_* がある。
Operating system events
この下にさらに Win32_* がある。
Operating system settings
この下にさらに Win32_* がある。
Processes
この下にさらに Win32_* がある。
Registry
この下にさらに Win32_* がある。
Scheduler jobs
この下にさらに Win32_* がある。
Security
この下にさらに Win32_* がある。
Services
この下にさらに Win32_* がある。
Shares
この下にさらに Win32_* がある。
Start menu
この下にさらに Win32_* がある。
Users
この下にさらに Win32_* がある。
Windows NT event log
この下にさらに Win32_* がある。
Windows Product Activation
この下にさらに Win32_* がある。
Installed applicationsWin32_ActionCheck
Win32_ApplicationCommandLine
Win32_ApplicationService
Win32_Binary
Win32_BindImageAction
Win32_CheckCheck
Win32_ClassInfoAction
Win32_CommandLineAccess
Win32_Condition
Win32_CreateFolderActionl
Win32_DuplicateFileAction
Win32_EnvironmentSpecification
Win32_ExtensionInfoAction
Win32_FileSpelcification
Win32_FontInfolAction
Win32_IniFileSpecification
Win32_InstalledSoftwareElement
Win32_LaunchCondition
Win32_ManagedSystemElementResource
Win32_MIMEInfoAction
Win32_MoveFileAction
Win32_MSIResource
Win32_ODBCAttribute
Win32_ODBCDataSourceAttribute
Win32_ODBCDataSourceSpecification
Win32_ODBCDlriverAttribute
Win32_ODBCDriverSoftwareElement
Win32_ODBCDriverSpecification
Win32_ODBCSourceAttribute
Win32_ODBCTranslatorSpecification
Win32_Patch
Win32_PatchFile
Win32_PatchPackage
Win32_Product
Win32_ProductCheck
Win32_ProductResource
Win32_ProductSoftwareFeatures
Win32_ProgIDSpecification
Win32_Property
Win32_PublishComponentAction
Win32_RegistryAction
Win32_RemoveFileAction
Win32_RemoveIniAction
Win32_ReserveCost
Win32_SelfRegModuleAction
Win32_ServiceControl
Win32_ServiceSpecification
Win32_ServiceSpecificationService
Win32_SettingCheck
Win32_ShortcutAction
Win32_ShortcutSAP
Win32_SoftwareElement
Win32_SoftwareElementAction
Win32_SoftwareElementCheck
Win32_SoftwareElementCondition
Win32_SoftwareElementResource
Win32_SoftwareFeature
Win32_SoftwareFeatureAction
Win32_SoftwareFeatureCheck
Win32_SoftwareFeatureParent
Win32_SoftwareFeatureSoftwareElements
Win32_TypeLibraryAction
WMI service managementWin32_MethodParameterClass
Win32_WMISetting
Win32_WMIElementSetting
Performance countersFormatted Performance Counter Classes
この下にさらに Win32_* が山のようにある。
Raw Performance Counter Classes
この下にさらに Win32_* が山のようにある。
      

4−1.プロセッサーの情報を取得する。


さて、ここで、WIn32_* で取得した ManagementObject に対して、 mo["Name"]で値を書き出していますが、取れる情報はクラスによって異なります。
例えば、Processor の情報を取得するコードを書いてみました。
Processor の情報を取得する。
            Console.WriteLine("---------------- Processor ------------------");
            try 
            {
                ManagementClass managementClass = new ManagementClass("Win32_Processor");
                ManagementObjectCollection managementObj = managementClass.GetInstances();

                foreach(ManagementObject mo in managementObj)
                {
                    Console.WriteLine("AddressWidth:\t{0}", mo["AddressWidth"]);
                    // Architecture
                    ushort arch = (ushort)mo["Architecture"];
                    string[] architecture = {"x86", "MIPS", "Alpha", "PowerPC", "Unknown"};
                    if (arch <= 3)
                        Console.WriteLine("Architecture:\t {0}", architecture[arch]);
                    else
                        Console.WriteLine("Architecture:\t Unknown");
                    Console.WriteLine("Architecture:\t {0}", architecture[arch]);
                    // Availability
                    ushort avail = (ushort)mo["Availability"];
                    string[] availability = {
                                                "-", "Other", "Unknown", "Running/Full Power", "Warning", "In Test",
                                                "Not Applicable", "Power Off", "Off Line", "Off Duty", "Degraded",
                                                "Not Installed", "Install Error", "Power Save - Unknown", "Power Save - Low Power Mode", "Power Save - Standby",
                                                "Power Cycle", "Power Save - Warning", "Paused", "Not Ready", "Not Configured",
                                                "Quiesced"
                                            };
                    if (avail <= 21)
                        Console.WriteLine("Availability:\t {0}", availability[avail]);
                    else
                        Console.WriteLine("Availability:\t Unknown");
                    // Caption
                    Console.WriteLine("Caption :\t{0}", mo["Caption"]);
                    Console.WriteLine("ConfigManagerErrorCode:\t{0}", mo["ConfigManagerErrorCode"]);
                    Console.WriteLine("ConfigManagerUserConfig:\t{0}", mo["ConfigManagerUserConfig"]);
                    // CpuStatus
                    ushort cpuStat = (ushort)mo["CpuStatus"];
                    string[] cpuStatus = {
                                             "-", "Unknown", "CPU Enabled", "CPU Disabled by User via BIOS Setup", "CPU Disabled By BIOS (POST Error)", "CPU is Idle",
                                             "Reserved", "Reserved", "Other",
                    };
                    if (cpuStat <= 8)
                        Console.WriteLine("CpuStatus:\t {0}", cpuStatus[cpuStat]);
                    else
                        Console.WriteLine("CpuStatus:\t Unknown");

                    // CreationClassName
                    Console.WriteLine("CreationClassName:\t{0}", mo["CreationClassName"]);
                    Console.WriteLine("CurrentClockSpeed:\t{0} MHz", mo["CurrentClockSpeed"]);
                    // CurrentVoltage
                    ushort cv = (ushort)mo["CurrentVoltage"];
                    Console.WriteLine("CurrentVoltage:\t{0} V", (float)cv/10F);
                    Console.WriteLine("DataWidth:\t{0} bit", mo["DataWidth"]);
                    Console.WriteLine("Description:\t{0}", mo["Description"]);
                    Console.WriteLine("DeviceID:\t{0}", mo["DeviceID"]);
                    Console.WriteLine("ErrorCleared:\t{0}", mo["ErrorCleared"]);
                    Console.WriteLine("ErrorDescription:\t{0}", mo["ErrorDescription"]);
                    Console.WriteLine("ExtClock:\t{0} MHz", mo["ExtClock"]);
   
                    // Family
                    string[] family = {
                                        "Other", "Unknown", "8086", "80286", "80386", "80486", // 0-  
                                          "8087", "80287", "80387", "80487", "Pentium Family", // 6-
                                          "Pentium Pro", "Pentium II", "Pentium MMX", "Celeron", "Pentium II Xeon", // 11-
                                          "Pentium III", "M1 Family", "M2 Family", "K5 Family", "K6 Family", // 16-
                                          "K6-2", "K6-III", "Athlon", "Power PC Family", "Power PC 601", // 21-
                                          "Power PC 603", "Power PC 603+", "Power PC 604", "Alpha Family", "MIPS Family", // 26-
                                          "SPARC Family", "68040", "68xxx Family", "68000", "68010", // 31-
                                          "68020", "68030", "Hobbit Family", "Weitek", "PA-RISC Family", // 36-
                                          "V30 Family", "Pentium III Xeon", "AS400 Family", "IBM390 Family", "i860", // 41-
                                          "i960", "SH-3", "SH-4", "ARM", "StrongARM", // 46-
                                          "6x86", "MediaGX", "MII", "WinChip"  // 54-                                           
                                      };                  
                    ushort f = (ushort)mo["Family"];
                    if (f <= 54)
                        Console.WriteLine("Family:\t {0}, {1}", f, family[f]);
                    else
                        Console.WriteLine("Family:\t Unknown");

                    // InstallDate
                    Console.WriteLine("InstallDate:\t{0}", mo["InstallDate"]);
                    // L2CacheSize
                    Console.WriteLine("L2CacheSize:\t{0}", mo["L2CacheSize"]);
                    Console.WriteLine("L2CacheSpeed:\t{0}", mo["L2CacheSpeed"]);
                    Console.WriteLine("LastErrorCode:\t{0}", mo["LastErrorCode"]);
                    Console.WriteLine("Level:\t{0}", mo["Level"]);
                    Console.WriteLine("LoadPercentage:\t{0}", mo["LoadPercentage"]);
                    // Manufacturer
                    
                    Console.WriteLine("Manufacturer:\t{0}", mo["Manufacturer"]);
                    Console.WriteLine("MaxClockSpeed:\t{0}", mo["MaxClockSpeed"]);
                    
                    // Name
                    Console.WriteLine("Name:\t{0}", mo["Name"]);

                    // OtherFamilyDescription
                    Console.WriteLine("OtherFamilyDescription:\t{0}", mo["OtherFamilyDescription"]);
                    // PNPDeviceID 
                    Console.WriteLine("PNPDeviceID:\t{0}", mo["PNPDeviceID"]);
                    // PowerManagementCapabilities 
                    ushort [] pmArray = (ushort[])mo["PowerManagementCapabilities"];
                    string[] pms = {
                                          "Other", "Not Supported", "Disabled", "Enabled", "Power Saving Modes Entered Automatically", "Power State Settable",
                                          "Power Cycling Supported", "Timed Power On Supported"};
                    if (pmArray != null)
                        foreach(ushort p in pmArray)
                        {
                            if (p <= 7)
                                Console.WriteLine("PowerManagementCapabilities:\t {0}", pms[p]);
                            else
                                Console.WriteLine("PowerManagementCapabilities:\t Unknown");
                        }
                   
                    // PowerManagementSupported
                    Console.WriteLine("PowerManagementSupported:\t{0}", mo["PowerManagementSupported"].ToString()); 
                    Console.WriteLine("ProcessorId:\t{0}", mo["ProcessorId"]);
                    // ProcessorType 
                    ushort pType = (ushort)mo["ProcessorType"];
                    string[] proType = {
                                       "-", "Other", "Unknown", "Central Processor", "Math Processor", "DSP Processor",
                                       "Video Processor"};
                        if (pType <= 6)
                            Console.WriteLine("ProcessorType:\t {0}", proType[pType]);
                        else
                            Console.WriteLine("ProcessorType:\t Unknown");
                    // Revision 
                    Console.WriteLine("Revision:\t{0}", mo["Revision"].ToString());
                    Console.WriteLine("Role:\t{0}", mo["Role"]);
                    // SocketDesignation
                    Console.WriteLine("SocketDesignation:\t{0}", mo["SocketDesignation"]);
                    Console.WriteLine("Status:\t{0}", mo["Status"]);
                    Console.WriteLine("StatusInfo:\t{0}", mo["StatusInfo"].ToString());
                    Console.WriteLine("Stepping:\t{0}", mo["Stepping"]);
                    Console.WriteLine("SystemCreationClassName:\t{0}", mo["SystemCreationClassName"]);
                    Console.WriteLine("SystemName:\t{0}", mo["SystemName"]);
                    // UniqueId
                    Console.WriteLine("UniqueId:\t{0}", mo["UniqueId"]);
                    Console.WriteLine("UpgradeMethod:\t{0}", mo["UpgradeMethod"].ToString());
                    // Version 
                    Console.WriteLine("Version:\t{0}", mo["Version"]);
                    Console.WriteLine("VoltageCaps:\t{0}", mo["VoltageCaps"]);
 
                    Console.WriteLine("---------------- End of Processor ------------------");
                }
            }
            catch(Exception exc) 
            {
                Console.WriteLine(exc.Message);
            }
その実行結果
---------------- Processor ------------------
AddressWidth:   32
Architecture:    x86
Architecture:    x86
Availability:    Running/Full Power
Caption :       x86 Family 6 Model 7 Stepping 1
ConfigManagerErrorCode:
ConfigManagerUserConfig:
CpuStatus:       Unknown
CreationClassName:      Win32_Processor
CurrentClockSpeed:      1260 MHz
CurrentVoltage: 1.7 V
DataWidth:      32 bit
Description:    x86 Family 6 Model 7 Stepping 1
DeviceID:       CPU0
ErrorCleared:
ErrorDescription:
ExtClock:       105 MHz
Family:  29, Alpha Family       <<<<<<<<< MSのバグ? Duron なのに!
InstallDate:
L2CacheSize:    64
L2CacheSpeed:   420
LastErrorCode:
Level:  6
LoadPercentage: 99
Manufacturer:   AuthenticAMD
MaxClockSpeed:  1260
Name:   AMD Duron(tm) processor
OtherFamilyDescription:
PNPDeviceID:
PowerManagementSupported:       False
ProcessorId:    *****************:ちゃんととれましたが、一応目隠ししています。^^;
ProcessorType:   Central Processor
Revision:       1793
Role:   CPU
SocketDesignation:      Socket A
Status: OK
StatusInfo:     3
Stepping:       1
SystemCreationClassName:        Win32_ComputerSystem
SystemName:     UCHUKAMEN
UniqueId:
UpgradeMethod:  4
Version:        モデル 7, ステッピング 1
VoltageCaps:
---------------- End of Processor ------------------

このように、とんでもなく大量のデータを取得することができます。
このときのプログラムのデザインパターンは、次のとおりです。
            ManagementClass managementClass = new ManagementClass("Win32_Service");
            ManagementObjectCollection managementObj = managementClass.GetInstances();
            foreach(ManagementObject mo in managementObj)
                Console.WriteLine(mo["Name"]);
このときに、mo["プロパティ名"] で、所望のデータを取得することができます。

ポイント
このとき、このプロパティ名に何がサポートされているのか次のURL で調べればわかります。


http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wmisdk/wmi/win32_processor.asp

4−2.ネットワークコネクションの情報を取得する。

この例では、Win32_NetworkConnection クラスにより、ネットワークコネクションの情報を取得します。
結果からわかるように、\\uchukamen\test フォルダーを Z: ドライブにマウントしていることがわかります。
Processor の情報を取得する。
            Console.WriteLine("================= QueryNetworkConnection =================");
            try 
            {
                ManagementClass managementClass = new ManagementClass("Win32_NetworkConnection");
                ManagementObjectCollection managementObj = managementClass.GetInstances();

                foreach(ManagementObject mo in managementObj)
                {
                    Console.WriteLine("AccessMask:\t{0}", mo["AccessMask"]);
                    Console.WriteLine("Caption:\t{0}", mo["Caption"]);
                    Console.WriteLine("Comment:\t{0}", mo["Comment"]);
                    Console.WriteLine("ConnectionState:\t{0}", mo["ConnectionState"]);
                    Console.WriteLine("ConnectionType:\t{0}", mo["ConnectionType"]);
                    Console.WriteLine("Description:\t{0}", mo["Description"]);
                    Console.WriteLine("DisplayType:\t{0}", mo["DisplayType"]);
                    Console.WriteLine("InstallDate:\t{0}", mo["InstallDate"]);
                    Console.WriteLine("LocalName:\t{0}", mo["LocalName"]);
                    Console.WriteLine("Name:\t{0}", mo["Name"]);
                    Console.WriteLine("Persistent:\t{0}", mo["Persistent"]);
                    Console.WriteLine("ProviderName:\t{0}", mo["ProviderName"]);
                    Console.WriteLine("RemoteName:\t{0}", mo["RemoteName"]);
                    Console.WriteLine("RemotePath:\t{0}", mo["RemotePath"]);
                    Console.WriteLine("ResourceType:\t{0}", mo["ResourceType"]);
                    Console.WriteLine("Status:\t{0}", mo["Status"]);
                    Console.WriteLine("UserName:\t{0}", mo["UserName"]);
                    Console.WriteLine("-----------------------------------------");
                }
            }
            catch(Exception exc) 
            {
                Console.WriteLine(exc.Message);
            }
その実行結果
================= QueryNetworkConnection =================
AccessMask:
Caption:        RESOURCE REMEMBERED
Comment:
ConnectionState:        Disconnected
ConnectionType: Persistent Connection
Description:    RESOURCE REMEMBERED - Microsoft Windows Network
DisplayType:    Share
InstallDate:
LocalName:      Z:
Name:   \\uchukamen\test (Z:)
Persistent:     True
ProviderName:   Microsoft Windows Network
RemoteName:     \\uchukamen\test
RemotePath:     \\uchukamen\test
ResourceType:   Disk
Status: Degraded
UserName:       UCHUKAMEN\Uchukamen
-----------------------------------------

5.リモートコンピュータの WMI にアクセスする方法

リモートコンピュータに接続するには、次のようなコードを書く必要があります。

1.リモートコンピュータのユーザ名、パスワードを指定します。

注意:
このユーザ名は、コンピュータにアクセスするだけに十分な権限を持つ必要があります。

ここで、Managementラスにより、ネットワークコネクションの情報を取得します。
結果からわかるように、\\uchukamen\test フォルダーを Z: ドライブにマウントしていることがわかります。

Processor の情報を取得するデザインパターン。
                ConnectionOptions option = new ConnectionOptions(); 
                option.Username = "DomainName\\UserName"; 
                option.Password = "パスワードを入れる"; 
                ManagementScope scope = new ManagementScope("\\\\ServerName\\root\\cimv2", option);
                ObjectQuery query = new ObjectQuery("SELECT * FROM Win32_Processor"); 
                ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope,query); 
                ManagementObjectCollection moCollection = searcher.Get();   

                foreach(ManagementObject mo in moCollection)
                {
                    Console.WriteLine("Name:\t{0}", mo["Name"]);
                }

解説

1.リモートコンピュータのユーザ名、パスワードを指定します。
ConnectionOptions を使って、ユーザ名、パスワードを option に指定します。

注意:
このユーザ名は、コンピュータにアクセスするだけに十分な権限を持つ必要があります。
Impersonation プロパティは、デフォルトで Impersonate なので、指定する必要はありません。
2.管理操作のスコープを指定します。
ManagementScope を使って、管理操作のスコープを scope に指定します。
このとき、ConnectionOptions で、先ほどのユーザ名、パスワードを一緒に渡します。

注意:
通常は "root\\cimv2" がデフォルトですが、リモートの場合リモートサーバの場所を指定する必要があります。
3.Query を指定します。
これは、ローカルもリモートも同じです。
4.サーチャーを作ります。
ManagementObjectSearcherを、2で作ったスコープを指定してインスタンス化します。
あとは、同じでOK!


リモートコンピュータへ接続できない場合のチェックポイント

1.もともとシステムとして接続できないセキュリティなのか、このプログラムが間違っているのか、切り分ける。
まずは、イベントビューアを起動して、接続しようとしているリモートコンピュータへ接続してみてください。
つながれば、プログラムが間違っている可能性が高いです。

つながらなければ、もともと接続できるだけのセキュリティがないと思われます。
リモートでの Administrators グループへ属しているか、Administrator 権限を持っているユーザか確認しましょう。
2.Domain か、Workgroup か?
ドメインユーザの場合、option.Username = "DomainName\\UserName";
ワークグループの場合、option.Username = "リモートのコンピュータ名\\UserName";

注意:
ユーザ名はドメインユーザか、ローカルユーザかで異なります。
3.パスワードはあっているか?
自分のコンピュータのパスワードではありません。リモートのユーザのパスワードです。
4.XPで、ワークグループの設定の場合
XPではセキュリティが強化されており、ローカルアカウントの共有(同じユーザ名、同じパスワード)でリモートの
PCにログインできなくなっています。

このため、ローカルセキュリティ設定を変更します。
コントロールパネル→管理ツール→ローカルセキュリティポリシーを起動します。下図。
ここで、左ペインのローカルポリシー→セキュリティオプション→ネットワークアクセス:ローカルアカウントの共有とセキュリティモデルの
プロパティを開きます。
デフォルトでは、”Guestのみ − ローカルユーザーがGuestとして認証する。
になっていますが、これだといくらユーザ名、パスワードを設定してもだめです。
これを、クラシック ローカルユーザがローカルユーザとして認証する。に変更します。

注意:
これは、セキュリティの危険を増大させます。十分理解したうえで、オウンリスクで実施してください。
パスワードを設定していないでこの設定を行うと、セキュリティ上丸裸になります。


実は、なかなかリモートに接続できず、このことに気がつくまで、2日かかりました。
ほとんどあきらめかけましたが、なんとか探し当てました。奥が深い。
っていゆか、マニュアルに書いておけよ!>>MS

注意:
これは、自分の環境(Win XP → Win XP) でしか試してません。
こればかりは、環境ごとに解決するしかないので、接続できなくても、質問しないでね ^__^/ 。


Image

5−1.リモートコンピュータのプロセッサー情報を取得する。


この例では、4−1で作ったプロセッサーの情報を取得するプログラムを修正して、リモートコンピュータの
プロセッサーの情報を取得するプログラムです。

前述のデザインパターンに最初の数行を修正すればOKです。

Processor の情報を取得する。
            Console.WriteLine("================= QueryRemoteProcessor =================");
            try 
            {
                ConnectionOptions option = new ConnectionOptions(); 
                option.Username = "DomainName\\UserName"; 
                option.Password = "パスワードを入れる"; 
                ManagementScope scope = new ManagementScope("\\\\ServerName\\root\\cimv2", option);
                ObjectQuery query = new ObjectQuery("SELECT * FROM Win32_Processor"); 
                ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope,query); 
                ManagementObjectCollection moCollection = searcher.Get();   

                foreach(ManagementObject mo in moCollection)
                {
                    Console.WriteLine("AddressWidth:\t{0}", mo["AddressWidth"]);
                    // Architecture
                    ushort arch = (ushort)mo["Architecture"];

          中略中略中略中略中略中略中略中略中略中略中略中略中略中略中略中略

                    Console.WriteLine("VoltageCaps:\t{0}", mo["VoltageCaps"]);
                    
                    Console.WriteLine("-----------------------------------------");
                }
            }
            catch(Exception exc) 
            {
                Console.WriteLine(exc.Message);
            }
その実行結果
これは、実際にネットに接続されているPCのプロセッサ情報をリモートで取得したものです。
しょぼいPCを使っているのがばれてしまった。^^;

================= QueryRemoteProcessor =================
AddressWidth:   32
Architecture:    x86
Architecture:    x86
Availability:    Running/Full Power
Caption :       x86 Family 6 Model 6 Stepping 10
ConfigManagerErrorCode:
ConfigManagerUserConfig:
CpuStatus:       Unknown
CreationClassName:      Win32_Processor
CurrentClockSpeed:      333 MHz
CurrentVoltage: 2.9 V
DataWidth:      32 bit
Description:    x86 Family 6 Model 6 Stepping 10
DeviceID:       CPU0
ErrorCleared:
ErrorDescription:
ExtClock:       66 MHz
Family:  15, Pentium II Xeon
InstallDate:
L2CacheSize:    128
L2CacheSpeed:   333
LastErrorCode:
Level:  6
LoadPercentage: 5
Manufacturer:   GenuineIntel
MaxClockSpeed:  333
Name:   Intel Celeron プロセッサ
OtherFamilyDescription:
PNPDeviceID:
PowerManagementSupported:       False
ProcessorId:    ******************
ProcessorType:   Central Processor
Revision:       1546
Role:   CPU
SocketDesignation:      240PIN BGA SOCKET
Status: OK
StatusInfo:     3
Stepping:       10
SystemCreationClassName:        Win32_ComputerSystem
SystemName:     *******
UniqueId:
UpgradeMethod:  6
Version:        モデル 6, ステッピング 10
VoltageCaps:    4
-----------------------------------------

6. WMI のその他の機能(メソッドインボケーション、イベント生成、関連付け)

WMI 管理クラスでは、次の4つ情報を扱えます。 4章、5章で扱ってきたのは、プロパティを使用しただけで、このような強力な機能があります。

 

プロパティたとえば、Win32_Processor クラスのプロパティを取得します。
メソッドたとえば、Win32_Directoryクラスには、Compress()というメソッドがあります。
これを使って、フォルダの内容を Windows のグラフィカル ユーザー インターフェイスを通じて行うのと同じように圧縮することができます。
イベントたとえば、Win32_ProcessorクラスのLoadPercentageプロパティを使って、
CPU 占有率が 50 パーセントを超えるたびにイベントを生成するようにリクエストできます。
関連付け関連付けとは、クラス間の関係を表し、それ自身、クラスによって定義されます。
関連付けの例に、ダイアルアップ モデムとそれが接続されている通信ポートのインスタンスへの参照を含む
Win32_POTSModemToSerialPortクラスがあります。これは非常に強力な概念です。
というのは、これによってトラブルシューティングなどの作業のときに、互いに関連のあるコンポーネントで
構成されているシステム全体の管理情報を参照したり、たどったりできるからです。

直訳で、よくわかっていません。

注意: 

実際に使って試してないので、何とも言えません。^^;
実際に使う必要が出たときに考えます。
リモートメソッドインボケーションなんてつかわないだろうし。。。