CIM to WMI

Years ago WMI was de-emphasized for CIM. Wait. Do you know what those are?

CIM“The Common Information Model (CIM) is an extensible, object-oriented data model that contains information about different parts of an enterprise. Through WMI, a developer can use the CIM to create classes that represent hard disk drives, applications, network routers, or even user-defined technologies, such as a networked air conditioner. By viewing and making changes to a CIM class, a manager can control different aspects of the enterprise. For example, a manager could query a CIM class instance representing a desktop workstation. The manager could then run a script to modify the CIM workstation instance. WMI would translate any change to the workstation CIM class instance into a change to the actual workstation.” https://docs.microsoft.com/en-us/windows/win32/wmisdk/common-information-model

WMI“WMI provides a uniform interface for any local or remote applications or scripts that obtain management data from a computer system, a network, or an enterprise. The uniform interface is designed such that WMI client applications and scripts do not have to call a wide variety of operating system application programming interfaces (APIs). Many APIs cannot be called by automation clients like scripts or Visual Basic applications. “ https://docs.microsoft.com/en-us/windows/win32/wmisdk/wmi-architecture

CIM was introduced in 2016 as a better version of WMI. A good quick read of the why is also listed here – https://devblogs.microsoft.com/scripting/should-i-use-cim-or-wmi-with-windows-powershell/

Now that we have the formal definitions and working models out of the way, let’s review how this can be used in the real world. In these code examples we’ll basically try to use CIM and have a way to use WMI if the CIM cmdlets failed.

CIM to WMI Example #1

In this example, we are using CIM or WMI to query the Maximum Pagefile size. The intent is to see if the Pagefile is configured correctly. The first part of the code initiates a CIM query which if it fails, will set the $WMIQuery variable to $True. This will then initiate a WMI Query for the same values as the CIM query:
[sourcecode language=”powershell”]
# Query Maximum Pagefile size:
Try {
$MaximumSize = (Get-CimInstance -ComputerName $Server -Query "Select * from win32_PageFileSetting" -ErrorAction STOP| select-object MaximumSize).MaximumSize
} Catch {
$WMIQuery = $True
}

# If the CIM query fails, use WMI
If ($WMIQuery) {
Try {
$MaximumSize = (Get-WMIObject -ComputerName $Server -Class win32_PageFileSetting -ErrorAction STOP | select-object MaximumSize).MaximumSize
} Catch {
$MaximumSize = 'Managed'
}
}
[/sourcecode]

CIM to WMI Example #2

In this example, we have a series of computers that we need to query options on and we us the exact same method. In this case, the computers could be domain joined, where the CIM query should work and some computers that are in a Workgroup, which will fail the CIM query, but allow a WMI query.
[sourcecode language=”powershell”]
# Get Exchange Edge Transport Servers
$EdgeSubscriptions = Get-EdgeSubscription -ErrorAction Stop | Select Name,Site,Domain,IsValid
Foreach ($EdgeSubscription in $EdgeSubscriptions) {
$EdgeServer = $EdgeSubscription.Name
$EdgeServers += $EdgeServer
}
Foreach ($Server in $EdgeServers) {
# Query Maximum Pagefile size:
Try {
$Os = Get-CIMInstance Win32_OperatingSystem -Namespace "root\CIMV2" -Computername $Server -ErrorAction STOP
} Catch {
$WMIQuery = $True
}

# If the CIM query fails, use WMI
If ($WMIQuery) {
Try {
$os = Get-WmiObject Win32_OperatingSystem -Namespace "root\CIMV2" -Computername $Server -ErrorAction STOP
} Catch {
$MaximumSize = 'Managed'
}
}
}
[/sourcecode]
In this case we are planning for CIM to fail and use WMI as our backup. For Exchange Edge Transport, PowerShell will fail CIM and the use WMI to query the servers. The reason that CIM fails is that PowerShell wants to authenticate one way, but fails, which causes CIM to fail. Then WMI kicks in and can make a connection to the remote server.

The driving factor for the failover to WMI from CMI is that the CMI cmdlet (Get-CIMInstance) fails which triggers the ErrorAction parameter. When that fails, the $WMIQuery variable is set to $True. Then when PowerShell sees if ($WMIQuery), the code block in the IF() {} block is executed.

One caveat to this, some environments block these CMI/WMI queries. If this occurs, the blocks may need to be removed. Something to be aware of.

Conclusion

As you can see from the examples above, they follow similar processes, but they are used for different purposes. One because it assumes that CIM will work, but hopefully WMI will work. Whereas Example #2 is because it allows for queries of domain joined and workgroup based servers. Both have their purposes. In the end, Example #1 should be the most common usage and if you are using CIM, plan for WMI failback just in case.

Related Post