PowerShell CIM

PowerShell CIM helps solving a problem with old RPC way of getting WMI data. The problem when using PowerShell to get WMI data from remote computers, is that WMI usually need to connect to an RPC endpoint in the remote computer. In restricted environment or data center, RPC is usually blocked, especially between different subnets or networks.

There is a better way that doing WMI via RPC, and that is CIM. The PowerShell CIM cmdlets appeared in PowerShell 3.0 as part of the new API for working with CIM classes, which is more standards based. The big difference between the WMI cmdlets and the CIM cmdlets is that the CIM cmdlets use WSMAN (WinRM) to connect to remote machines.

so CIM is more standardized way, and firewall friend way to connect. While transitioning from using RPC way to using PowerShell CIM way, you need a simple method of trying to connect using CIM, and if this did not work out, to try the old way just in case. After all, you want to get data no matter what.

I created a script command Get-CorpCimInfo, that you can invoke instead of Get-WMIObject. If you run the script using -verbose mode, you will be presented with the right information for you to discover the power and logic of the script. Running the script by its own will not do anything as it is a wrapper function for you to use in other places where you need to get WMI data.

The script will basically get computer name or names, try to collect WMI information from them. The script is smart enough to test if the remote computer is running PowerShell 3.0 at least and supports WS-MAN 3.0. If this is the case, the script will try to get WMI information by creating PowerShell CIM session (Get-CIMSession).

If the script cannot connect to remote computer using CIM Session, then PowerShell Remoting will be tried. If this fails too, the script will try to fall back to RPC call to get WMI data.

Get-CorpCIMInfo is a wrapper. Instead of using Get-CIMSession, and then see if there is error, and fallback to using Get-WMIObject, this wrapper function will do this for you in one line of code. It comes with lot of switches to help you control which methods you want to use to get WMI data. The most secure way is tried first, which is WS-MAN 3.0. If we cannot get the WMI data using this way, the script will try PowerShell Remoting. If this is not available, DCOM is used as a fallback method

Get-CorpCIMInfo_232

After a quick chat with Jeffery Hicks (@JeffHicks) who I based my script upon his own version, Jeff suggested couple of modifications on my script, specifically the concept of always returning objects instead of strings or other types. After tweaking the script to do that and add more verbose and exception additional information, I came with version 2 of the script. You can download the script from here.

Examples

Get computer names from pipeline.

PS C:\> get-content computers.txt | Get-CorpCimInfo -class win32_logicaldisk -filter "drivetype=3"

When getting WMI data, do not use RPC at all

PS C:\> Get-CorpCimInfo -Class Win32_Bios "Localhost","Host1" -DisableDCOM

Only enable DCOM to access WMI information.

PS C:\> Get-CorpCimInfo -Class Win32_Bios "Localhost","Host1" -DisableWsman3 -DisableWsman2 -LegacyDCOM

Use Query parameter instead of ClassName

PS C:\> Get-CorpCimInfo -Query "SELECT * from Win32_Process WHERE name LIKE 'p%'" -ComputerName "Host1"