C# を使用した WMI へのリモート接続

PowerShell、VBScript、C++ などの他の言語と同様に、C# を使用して、リモート コンピューター上のハードウェアとソフトウェアをリモートで監視できます。 マネージド コードのリモート接続は、Microsoft.Management.Infrastructure 名前空間を介して行われます (以前のバージョンの WMI では System.Management 名前空間が使用されていました。完全性のために、ここでもこれについて説明しています)。

注意

System.Management は、元来 WMI へのアクセスに使用されていた .NET 名前空間でした。しかし、この名前空間の API は一般に、より最新の Microsoft.Management.Infrastructure の対応する API と比較して低速で、拡張性も劣ります。

 

Microsoft.Management.Infrastructure 名前空間のクラスを使用するリモート接続には、基になるリモート機構として DCOM が使用されます。 WMI のリモート接続は、偽装および認証に関する DCOM のセキュリティ要件に準拠している必要があります。 既定では、スコープはローカル コンピューターと "Root\CIMv2" システム名前空間に限定されています。 ただし、アクセスするコンピューター、ドメイン、WMI 名前空間を変更することもできます。 また、権限、偽装、資格情報、その他の接続オプションを設定することもできます。

C# を使用して WMI にリモート接続するには (Microsoft.Management.Infrastructure)

  1. CimSession.Create を呼び出して、リモート コンピューターでセッションを作成します。

    ログオンしているのと同じ資格情報 (ドメインとユーザー名) を使用してリモート コンピューターに接続している場合は、Create の呼び出しでコンピューターの名前を指定できます。 返された CimSession オブジェクトを取得したら、WMI クエリを作成できます。

    using Microsoft.Management.Infrastructure;
    ...
    string Namespace = @"root\cimv2";
    string OSQuery = "SELECT * FROM Win32_OperatingSystem";
    CimSession mySession = CimSession.Create("Computer_B");
    IEnumerable<CimInstance> queryInstance = mySession.QueryInstances(Namespace, "WQL", OSQuery);
    

    C# で Microsoft.Management.Infrastructure API を使用して WMI クエリを実行する方法の詳細については、「WMI クラスまたはインスタンス データの取得」を参照してください。

  2. 異なる資格情報、ロケール、偽装レベルなど、接続に異なるオプションを設定する場合は、CimSession.Create の呼び出しで CimSessionOptions オブジェクトを使用する必要があります。

    CimSessionOptions は、WSManSessionOptions および DComSessionOptions の基底クラスです。 いずれかを使用して、WS-Manセッションと DCOM セッションのオプションをそれぞれ設定できます。 次のコード サンプルでは、DComSessionOptions オブジェクトを使用して偽装レベルを Impersonate に設定する方法について説明します。

    string computer = "Computer_B"
    DComSessionOptions DComOptions = new DComSessionOptions();
    DComOptions.Impersonation = ImpersonationType.Impersonate;
    
    CimSession Session = CimSession.Create(computer, DComOptions);
    
  3. 接続の資格情報を設定する場合は、CimCredentials オブジェクトを作成して CimSessionOptions に追加する必要があります。

    次のコード サンプルでは、WSManSessionOptions クラスを作成し、適切な CimSessionOptions を指定して、それを CimSession.Create 呼び出しで使用する方法について説明します。

    string computer = “Computer_B”;
    string domain = “Domain1″;
    string username = “User1″;
    
    string plaintextpassword; 
    
    //Retrieve password from the user. 
    //For the complete code, see the sample at the bottom of this topic.
    
    CimCredential Credentials = new CimCredential(PasswordAuthenticationMechanism.Default, domain, username, securepassword); 
    
    WSManSessionOptions SessionOptions = new WSManSessionOptions();
    SessionOptions.AddDestinationCredentials(Credentials); 
    
    CimSession Session = CimSession.Create(computer, SessionOptions);
    

    一般に、アプリケーションにパスワードをハードコーディングしないことをお勧めします。上記のコード サンプルが示すように、可能な限り、ユーザーにパスワードを入力してもらい、安全に保存するようにしてください。

WMI は、リモート コンピューターのハードウェアおよびソフトウェアを監視することを目的としています。 WMI v1 では、リモート接続は ManagementScope オブジェクトを使用して行われます。

C# を使用して WMI にリモート接続するには (System.Management)

  1. コンピューターの名前と WMI パスを使用して ManagementScope オブジェクトを作成し、ManagementScope.Connect() を呼び出してターゲットに接続します。

    ログオンしているのと同じ資格情報 (ドメインとユーザー名) を使用してリモート コンピューターに接続している場合は、WMI パスを指定するだけで済みます。 接続したら、WMI クエリを作成できます。

    using System.Management;
    ...
    ManagementScope scope = new ManagementScope("\\\\Computer_B\\root\\cimv2");
    scope.Connect();
    ObjectQuery query = new ObjectQuery("SELECT * FROM Win32_OperatingSystem");
    ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope, query);
    

    C# で System.Management API を使用して WMI クエリを実行する方法の詳細については、「WMI クラスまたはインスタンス データの取得」を参照してください。

  2. 別のドメイン内のリモート コンピューターに接続する場合、または別のユーザー名とパスワードを使用する場合は、ManagementScope の呼び出しで ConnectionOptions オブジェクトを使用する必要があります。

    ConnectionOptions には、認証、偽装、ユーザー名、パスワード、およびその他の接続オプションを記述するためのプロパティが含まれています。 次のコード サンプルでは、ConnectionOptions を使用して偽装レベルを Impersonate に設定する方法について説明します。

    ConnectionOptions options = new ConnectionOptions();
    options.Impersonation = System.Management.ImpersonationLevel.Impersonate;
    
    ManagementScope scope = new ManagementScope("\\\\FullComputerName\\root\\cimv2", options);
    scope.Connect();
    
    ObjectQuery query = new ObjectQuery("SELECT * FROM Win32_OperatingSystem");
    ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope,query);
    

    一般に、他の方法が明示的に必要とされていない限り、偽装レベルを Impersonate に設定することをお勧めします。 また、名前とパスワードを C# コードに書き込まないようにしてください (可能であれば、実行時に動的に指定するようにユーザーに求めることができるかどうかを確認してください)。

    リモート WMI 接続でさまざまなプロパティを設定するその他の例については、ConnectionOptions リファレンス ページの「例」セクションを参照してください。

Microsoft.Management.Infrastructure の例

次の C# コード例 (TechNet のブログ投稿に基づく) は、CimCredentialsWSManSessionOptions を使用してリモート接続に資格情報を設定する方法を説明したものです。

using System;
using System.Text;
using System.Threading;
using Microsoft.Management.Infrastructure;
using Microsoft.Management.Infrastructure.Options;
using System.Security; 

namespace SMAPIQuery
{
    class Program
    {
        static void Main(string[] args)
        { 

            string computer = "Computer_B";
            string domain = "DOMAIN";
            string username = "AdminUserName";


            string plaintextpassword; 

            Console.WriteLine("Enter password:");
            plaintextpassword = Console.ReadLine(); 

            SecureString securepassword = new SecureString();
            foreach (char c in plaintextpassword)
            {
                securepassword.AppendChar(c);
            } 

            // create Credentials
            CimCredential Credentials = new CimCredential(PasswordAuthenticationMechanism.Default, 
                                                          domain, 
                                                          username, 
                                                          securepassword); 

            // create SessionOptions using Credentials
            WSManSessionOptions SessionOptions = new WSManSessionOptions();
            SessionOptions.AddDestinationCredentials(Credentials); 

            // create Session using computer, SessionOptions
            CimSession Session = CimSession.Create(computer, SessionOptions); 

            var allVolumes = Session.QueryInstances(@"root\cimv2", "WQL", "SELECT * FROM Win32_Volume");
            var allPDisks = Session.QueryInstances(@"root\cimv2", "WQL", "SELECT * FROM Win32_DiskDrive"); 

            // Loop through all volumes
            foreach (CimInstance oneVolume in allVolumes)
            {
                // Show volume information

                if (oneVolume.CimInstanceProperties["DriveLetter"].ToString()[0] > ' '  )
                {
                    Console.WriteLine("Volume ‘{0}’ has {1} bytes total, {2} bytes available", 
                                      oneVolume.CimInstanceProperties["DriveLetter"], 
                                      oneVolume.CimInstanceProperties["Size"], 
                                      oneVolume.CimInstanceProperties["SizeRemaining"]);
                }

            } 

            // Loop through all physical disks
            foreach (CimInstance onePDisk in allPDisks)
            {
                // Show physical disk information
                Console.WriteLine("Disk {0} is model {1}, serial number {2}", 
                                  onePDisk.CimInstanceProperties["DeviceId"], 
                                  onePDisk.CimInstanceProperties["Model"].ToString().TrimEnd(), 
                                  onePDisk.CimInstanceProperties["SerialNumber"]);
            } 

            Console.ReadLine();
         }
     }
 }

System.Management の例

次の C# コード サンプルは、System.Management オブジェクトを使用した一般的なリモート接続について説明したものです。

using System;
using System.Management;
public class RemoteConnect 
{
    public static void Main() 
    {
        ConnectionOptions options = new ConnectionOptions();
        options.Impersonation = System.Management.ImpersonationLevel.Impersonate;

        
        ManagementScope scope = new ManagementScope("\\\\FullComputerName\\root\\cimv2", options);
        scope.Connect();

        //Query system for Operating System information
        ObjectQuery query = new ObjectQuery("SELECT * FROM Win32_OperatingSystem");
        ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope,query);

        ManagementObjectCollection queryCollection = searcher.Get();
        foreach ( ManagementObject m in queryCollection)
        {
            // Display the remote computer information
            Console.WriteLine("Computer Name     : {0}", m["csname"]);
            Console.WriteLine("Windows Directory : {0}", m["WindowsDirectory"]);
            Console.WriteLine("Operating System  : {0}", m["Caption"]);
            Console.WriteLine("Version           : {0}", m["Version"]);
            Console.WriteLine("Manufacturer      : {0}", m["Manufacturer"]);
        }
    }
}

リモート コンピューター上の WMI への接続