WMI (Windows Management Instrumentation) is part of any Windows operating system and a common and widely used way of getting information about a computer system. PowerShell originally introduced the Get-WmiObject cmdlet. In PowerShell 3, the more modern Get-CimInstance was added.
Since Windows PowerShell always kept the old Get-WmiObject cmdlet for backwards compatibility, many scripters kept using it and ignored Get-CimInstance. Now is the time to break this old habit because PowerShell Core (PowerShell 6, 7) stopped support for Get-WmiObject. To make sure your scripts are compatible with future versions of PowerShell, you should start using Get-CimInstance instead of Get-WmiObject.
This seems trivial at first, and often it is. For simple data queries, you might get away with replacing Get-WmiObject by Get-CimInstance:
PS> Get-WmiObject -Class Win32_BIOS SMBIOSBIOSVersion : 1.0.9 Manufacturer : Dell Inc. Name : 1.0.9 SerialNumber : 4ZKM0Z2 Version : DELL - 20170001 PS> Get-CIMInstance -Class Win32_BIOS SMBIOSBIOSVersion : 1.0.9 Manufacturer : Dell Inc. Name : 1.0.9 SerialNumber : 4ZKM0Z2 Version : DELL - 20170001
Note that the -Class parameter actually was renamed to -ClassName in Get-CimInstance, but since PowerShell allows shortened parameter names as long as they are unique, you do not necessarily have to adjust the parameter name.
The truth is, however, that Get-WmiObject and Get-CimInstance are not 100% compatible, and there are important differences you should know, especially when you plan to make changes to existing scripts. In this mini-series, we’ll look at the most important practical differences.
Let’s look at the information returned by both commands. Here is an approach that looks at the returned properties:
# we are comparing this WMI class (feel free to adjust) $wmiClass = 'Win32_OperatingSystem' # get information about the WMI class Win32_OperatingSystem with both cmdlets $a = Get-WmiObject -Class $wmiClass | Select-Object -First 1 $b = Get-CimInstance -ClassName $wmiClass | Select-Object -First 1 # dump the property names and add the property "Origin" so you know # which property was returned by which command: $aDetail = $a.PSObject.Properties | Select-Object -Property Name, @{N='Origin'={'Get-WmiObject'}} $bDetail = $b.PSObject.Properties | Select-Object -Property Name, @{N='Origin'={'Get-CimInstance'}} # compare the results: Compare-Object -ReferenceObject $aDetail -DifferenceObject $bDetail -Property Name -PassThru | Sort-Object -Property Origin
And here is the result:
Name Origin SideIndicator ---- ------ ------------- CimClass Get-CimInstance => CimInstanceProperties Get-CimInstance => CimSystemProperties Get-CimInstance => Qualifiers Get-WmiObject <= SystemProperties Get-WmiObject <= Properties Get-WmiObject <= ClassPath Get-WmiObject <= Options Get-WmiObject <= Scope Get-WmiObject <= __PATH Get-WmiObject <= __NAMESPACE Get-WmiObject <= __SERVER Get-WmiObject <= __DERIVATION Get-WmiObject <= __PROPERTY_COUNT Get-WmiObject <= __RELPATH Get-WmiObject <= __DYNASTY Get-WmiObject <= __SUPERCLASS Get-WmiObject <= __CLASS Get-WmiObject <= __GENUS Get-WmiObject <= Site Get-WmiObject <= Container Get-WmiObject <=
The result shows that there are considerable differences when it comes to the metadata. While Get-WmiObject always returns the name of the computer where the query was conducted in its property “__Server” (two underscores), Get-CimInstance buries this information in CimSystemProperties:
PS> $b.CimSystemProperties Namespace ServerName ClassName Path --------- ---------- --------- ---- root/cimv2 DESKTOP-8DVNI43 Win32_Process PS> $b.CimSystemProperties.ServerName DESKTOP-8DVNI43
The good news is, though, that the specific properties for a class do not differ, so both commands return the same basic information about the operating system, the BIOS, or whatever else you queried. This line returns the properties that are the same:
Compare-Object -ReferenceObject $aDetail -DifferenceObject $bDetail -Property Name -IncludeEqual -ExcludeDifferent -PassThru | Sort-Object -Property Origin | Select-Object -Property Name, SideIndicator
Name SideIndicator ---- ------------- ProcessName == ParentProcessId == PeakPageFileUsage == PeakVirtualSize == PeakWorkingSetSize == Priority == PrivatePageCount == ProcessId == QuotaNonPagedPoolUsage == QuotaPagedPoolUsage == QuotaPeakNonPagedPoolUsage == PageFileUsage == QuotaPeakPagedPoolUsage == PSComputerName == ReadTransferCount == SessionId == Status == TerminationDate == ThreadCount == UserModeTime == VirtualSize == WindowsVersion == WorkingSetSize == ReadOperationCount == WriteOperationCount == PageFaults == OtherOperationCount == Handles == VM == WS == Path == Caption == CreationClassName == CreationDate == CSCreationClassName == CSName == Description == OtherTransferCount == CommandLine == ExecutionState == Handle == HandleCount == InstallDate == KernelModeTime == MaximumWorkingSetSize == MinimumWorkingSetSize == Name == OSCreationClassName == OSName == ExecutablePath == WriteTransferCount ==