连接到远程计算机上的 WMI

WMI 可用于管理和访问远程计算机上的 WMI 数据。 WMI 中的远程连接受 Windows 防火墙和 DCOM 设置的影响。 用户帐户控制 (UAC) 也可能需要更改某些设置。 但是,一旦设置正确,对远程系统的调用就与本地 WMI 调用非常相似。 但是,你可以选择通过使用不同的凭据、备用身份验证协议和其他安全功能来使这种调用变得更复杂。

为远程连接配置计算机

在可以使用 WMI 访问远程系统之前,可能需要检查一些安全设置以确认你有访问权限。 具体而言:

  • Windows 包含许多安全功能,这些功能可能会阻止访问远程系统上的脚本。 因此,在发出 WMI 调用之前,你可能需要修改系统的 Active Directory 和 Windows 防火墙设置。 有关详细信息,请参阅设置远程 WMI 连接排查远程 WMI 连接问题

  • 必须启用正确的 DCOM 设置才能正常进行远程连接。 更改 DCOM 设置可以允许低权限用户访问计算机以进行远程连接。 有关详细信息,请参阅保护远程 WMI 连接

此外,在某些情况下,你可能希望通过固定端口运行 WMI。 为此,还需要更改设置。 有关详细信息,请参阅为 WMI 设置固定端口

Connecting to a Remote Computer

从本质上讲,使用 WMI 连接到远程系统需要确保你对系统拥有适当的访问权限,并确保正确配置了连接。 满足这两个要素后,连接本身相对比较简单。 例如,如果你使用默认安全凭据,则可以使用以下代码访问远程系统上的 WMI:

使用 PowerShell 远程连接到 WMI

使用大多数 WMI cmdlet 通用的 -ComputerName 参数,例如 Get-WmiObject

$strComputer = "Computer_B"
$colSettings = Get-WmiObject Win32_OperatingSystem -ComputerName $strComputer

使用 VBScript 远程连接到 WMI

GetObject 调用中使用包含远程系统名称的名字对象。

strComputer = "Computer_B"
Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Set colSettings = objWMIService.ExecQuery("Select * from Win32_OperatingSystem")

使用 C# 远程连接到 WMI

对于当前版本的 WMI 托管接口 (Microsoft.Management.Infrastructure),请使用 CimSession 对象来表示与远程主机的连接。

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# 远程连接到 WMI

对于 v1 版 WMI 托管接口 (System.Management),请使用 ManagementScope 对象来表示与远程主机的连接。

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

示例:从远程计算机获取 WMI 数据 (C++)

使用 IWbemLocator::ConnectServer 方法在 strNetworkResource 参数中指定远程计算机的名称。

    hres = pLoc->ConnectServer(
        _bstr_t(L"\\\\COMPUTER_B\\root\\cimv2"),
        _bstr_t(useToken?NULL:pszName),    // User name
        _bstr_t(useToken?NULL:pszPwd),     // User password
        NULL,                              // Locale             
        NULL,                              // Security flags
        _bstr_t(useNTLM?NULL:pszAuthority),// Authority        
        NULL,                              // Context object 
        &pSvc                              // IWbemServices proxy
        );

前面的代码示例可以说是能够通过 WMI 执行的最基本远程连接。 具体而言,这样示例的假设条件如下:

  • 你是远程计算机上的管理员。 由于用户帐户控制,远程系统上的帐户必须是管理员组中的域帐户。 有关详细信息,请参阅“用户帐户控制和 WMI”。
  • 当前本地计算机上的密码不是空白的。 这本质上是一项 Windows 安全要求,你必须使用密码登录到系统。
  • 本地计算机和远程计算机在同一个域中。 如果你需要跨越域边界,则需要提供额外的信息,或使用略有不同的编程模型。
  • 你正在使用自己的帐户访问远程计算机。 如果你尝试访问其他帐户,则需要提供额外的凭据。 (请注意,不允许使用与当前帐户不同的凭据尝试在本地访问 WMI。)
  • 两台计算机都运行 IPv6。 WMI 支持连接到运行 IPv6 的计算机。 但是,本地计算机和“Computer_B”都必须运行 IPv6。 任何一台计算机可能也在运行 IPv4。 有关详细信息,请参阅 WMI 中的 IPv6 和 IPv4 支持
  • 脚本不需要委托 – 也就是说,它不需要通过目标远程计算机访问其他远程计算机。 有关详细信息,请参阅使用 WMI 进行委托
  • 你正在尝试发出特定的调用,而不是创建远程进程。 有关详细信息,请参阅使用 WMI 远程创建进程

考虑到这些限制,远程 WMI 调用与本地 WMI 调用非常相似 – 唯一的差别在于,必须指定远程系统的名称。 但是,你可以选择更改其中的许多功能:使用不同的凭据、通过第三方计算机路由调用,或访问不同的域。