使用 C 远程连接到 WMI#

与 PowerShell、VBScript 或 C++ 等其他语言一样,可以使用 C# 远程监视远程计算机上的硬件和软件。 托管代码的远程连接是通过 Microsoft.Management.Infrastructure 命名空间完成的。 (以前版本的 WMI 使用了 System.Management 命名空间,此处包含用于 completeness.)

注意

System.Management 是用于访问 WMI 的原始 .NET 命名空间;但是,此命名空间中的 API 通常较慢,并且与其更现代 的 Microsoft.Management.Infrastructure 对应项相比,它们不会进行缩放。

 

使用 Microsoft.Management.Infrastructure 命名空间中的类远程连接使用 DCOM 作为基础远程机制。 WMI 远程连接必须符合 DCOM 对模拟和身份验证的安全要求。 默认情况下,范围绑定到本地计算机和“Root\CIMv2”系统命名空间。 但是,可以更改访问的计算机、域和 WMI 命名空间。 还可以设置颁发机构、模拟、凭据和其他连接选项。

使用 C# (Microsoft.Management.Infrastructure) 远程连接到 WMI

  1. 使用对 CimSession.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 对象。

    CimSessionOptionsWSManSessionOptionsDComSessionOptions 的基类。 可以使用任一选项分别在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# (System.Management) 远程连接到 WMI

  1. 使用计算机名称和 WMI 路径创建 ManagementScope 对象,并使用对 ManagementScope 的调用连接到目标。连接 () 。

    如果要使用与 (域和用户名相同的凭据连接到远程计算机,) 登录,则只需指定 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 将模拟级别设置为模拟。

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

    通常,建议将模拟级别设置为模拟,除非另有明确需要。 此外,请尝试避免将名称和密码写入 C# 代码。 (如果可能,请查看是否可以查询用户以在 runtime.) 动态提供它们

    有关在远程 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