Difference between Invoke-Command and query direct

2019-07-26 03:04发布

问题:

I'm currently working on a script that queries the disk information from a server. I'm stack with a problem and I really don't know whats going on here. May you can help me.

The following code is working (ComputerName replaced):

$space1 = Invoke-Command -ComputerName "xxxxxx" -ScriptBlock {
    Get-WmiObject -Class Win32_LogicalDisk -Filter "DeviceID='C:'"
}

This code works kinda well and may takes around 2 seconds to execute. After some experimenting I found a way how I can query it even faster. With all other servers it works fine, but for this server it simply doesn't work. Here' the code:

$space1 = Get-WmiObject -ComputerName "xxxxxx" -Class Win32_LogicalDisk -Filter "DeviceID='C:'"

This code takes around ~40 seconds to run, and then ends with the following error:

Get-WmiObject : The RPC server is unavailable. (Exception from HRESULT:
0x800706BA)
At line:1 char:10
+ $test1 = Get-WmiObject -ComputerName "xxxxxx" -Class Win32_LogicalD ...
+          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [Get-WmiObject], COMException
    + FullyQualifiedErrorId : GetWMICOMException,Microsoft.PowerShell.Commands.GetWmiObjectCommand

Can someone explain to me why it works fine with Invoke-Command but not when I use the ComputerName param on the Get-WmiObject directly? As said, for all my other servers this works fine and the code is faster so I would like to always use this code.

What I've done so far:

  • I checked the server for DNS and I tested similar commands.
  • Tried some other WmiObject commands, seems like always the RPC is not available.

What I think the problem could be:

I think the RPC protocol is disabled on the server. Does somebody know how to check that? Haven't found really anything that worked through Google...

What seems special:

CimInstance commands works. Do they use the RPC protocol too, or do they use another protocol? Haven't found any information on that one. Here the code I tested with:

Get-CimInstance -ComputerName "ccccc" -ClassName Win32_OperatingSystem

回答1:

Microsoft's WMI troubleshooting guide classifies the error as a firewall issue:

Error
0x800706BA–HRESULT_FROM_WIN32(RPC_S_SERVER_UNAVAILABLE)
Firewall issue or server not available.

Possible Issues
The computer really doesn't exist The Windows Firewall is blocking the connection

Solution
Connecting to Vista: netsh advfirewall firewall set rule group="windows management instrumentation (wmi)" new enable=yes. Connecting to downlevel: Allow the "Remote Administration" rule in Windows Firewall.

The difference between Get-WmiObject on the one hand and Get-CimInstance and Invoke-Command on the other hand is that the former uses DCOM for the network communication, while the latter use WinRM. See the article "Should I use CIM or WMI with Windows PowerShell" on the Scripting Guys blog for more information about the differences between WMI and CIM.

The DCOM protocol is based on RPC and uses port 135/tcp for the RPC endpoint mapper, which then assigns a random port between 1024 and 65535 for the actual RPC connection. WinRM on the other hand uses only one of two ports: 5985 for HTTP connections an 5986 for HTTPS connections, so it's a lot more firewall-friendly, and enabling WinRM/PowerShell Remoting already opens the ports in the firewall. That's most likely the reason why Invoke-Command and Get-CimInstance work, while Get-WmiObject doesn't.

As for the RPC protocol being disabled: that's not possible. Windows relies heavily on RPC for internal communication. If you actually disabled the protocol Windows would simply stop working.