In this mini-series, we are looking at the differences between Get-WmiObject and Get-CimInstance. Future PowerShell versions no longer support Get-WmiObject, so it is time to switch to Get-CimInstance if you haven’t already.
In the previous part you learned that there are considerable differences when you query information across a network, and that Get-CimInstance can use fully configurable and reusable session objects that help make network access faster and less resource intense.
Since Get-CimInstance works like a web service and unlike Get-WmiObject is not based on DCOM, this has important implications on the returned data. Get-CimInstance always goes through serialization, so you always and inevitably receive copies, never original objects. This is why Get-CimInstance never returns methods. You always just get properties.
Here is a practical example: the WMI class Win32_Process has a method called GetOwner() which returns the owner of a process. If you wanted to find out who is logged on to your machine, you could ask for explorer.exe processes and list their owners:
# find all explorer.exe instances Get-WmiObject -Class Win32_Process -Filter 'Name="explorer.exe"' | ForEach-Object { # call the WMI method GetOwner() $owner = $_.GetOwner() if ($owner.ReturnValue -eq 0) { # return either the process owner... '{0}\{1}' -f $owner.Domain, $owner.User } else { # ...or the error code 'N/A (Error Code {0})' -f $owner.ReturnValue } } | # remove duplicates Sort-Object -Unique
If you wanted to transition this code to Get-CimInstance, you cannot directly access the method GetOwner() because Get-CimInstance only returns a set of properties. Instead, you need to call the method via Invoke-CimMethod:
# find all explorer.exe instances Get-CimInstance -ClassName Win32_Process -Filter 'Name="explorer.exe"' | ForEach-Object { # call the WMI method GetOwner() $owner = $_ | Invoke-CimMethod -MethodName GetOwner if ($owner.ReturnValue -eq 0) { # return either the process owner... '{0}\{1}' -f $owner.Domain, $owner.User } else { # ...or the error code 'N/A (Error Code {0})' -f $owner.ReturnValue } } | # remove duplicates Sort-Object -Unique
Invoke-CimMethod either expects CimInstances to work with, or you can combine it with the original query, which simplifies the code further:
# find all explorer.exe instances Invoke-CimMethod -Query 'Select * From Win32_Process Where Name="explorer.exe"' -MethodName GetOwner | ForEach-Object { if ($_.ReturnValue -eq 0) { # return either the process owner... '{0}\{1}' -f $_.Domain, $_.User } else { # ...or the error code 'N/A (Error Code {0})' -f $_.ReturnValue } } | # remove duplicates Sort-Object -Unique
Invoke-CimMethod can also call static WMI methods which are methods that reside in the WMI class itself rather than a specific instance. If you wanted to create a new process (launch a new program) locally or remotely, you can use a line like this:
PS> Invoke-CimMethod -ClassName Win32_Process -MethodName "Create" -Arguments @{ CommandLine = 'notepad.exe'; CurrentDirectory = "C:\windows\system32" } ProcessId ReturnValue PSComputerName --------- ----------- -------------- 3308 0
Important: if you launch a program on a remote computer, it will run in your own hidden logon session and not be visible on the screen.