Optimizing WMI queries using forward only enumerators

I was writing a script that runs queries to about 2000 servers to check the patch compliance of each server, using WMI to query the SCCM agent on each machine. The servers are located all around the world, with varying degree of latency. Even though I utilize runspaces to speed things up, I still noticed that some of the threads timed out on me. Investigating I found out that it was the WMI query itself that took a long time executing, particularly on high-latency sites.

So I started investigating how I could optimize things, and came over the topic of using forward only enumerators. After some tests it became clear that I was on the right track.

This is the test script that I used:

$ComputerName = 'TestServer'
$wmiQueryString = 'SELECT UpdateID FROM CCM_TargetedUpdateEX1 WHERE UpdateState = 0'
$wmiNamespace = 'root\ccm\SoftwareUpdates\DeploymentAgent'

Clear-Host
Write-Host ""

Write-Host 'Using "regular" WMI query:'
Measure-Command {
	Get-WmiObject -Namespace $wmiNamespace -Query $wmiQueryString -Computer $ComputerName
} | Select Seconds,Milliseconds | Format-Table -AutoSize

Write-host ""

Write-Host 'Using forward only enumerator:'
Measure-Command {
	$enumOptions = New-Object System.Management.EnumerationOptions
	$enumOptions.Rewindable = $false
	$wmiScope = New-Object System.Management.ManagementScope("\\$computerName\$($wmiNamespace)")
	$wmiQuery = New-Object System.Management.ObjectQuery $wmiQueryString
	$wmiResults = New-Object System.Management.ManagementObjectSearcher $wmiScope, $wmiQuery, $enumOptions
	$result = $wmiResults.Get()
} | Select Seconds,Milliseconds | Format-Table -AutoSize

Below you can see the result of running this script:

wmitimings

As you can see, the speed improvement are not insignificant!

The only gotcha regarding using forward only enumerators are the fact that you can only enumerate them once! Consider this:

wmiresult

As you see, I call the count method twice. The first time it enumrates the object and gives me the result. The next time I call the count it only returns 0!

So If you are fine with that limitation, this little “trick” will save you precious seconds running your WMI queries.

2 comments

  1. Interesting approach. I will defenitly look more into that.
    Concerning your Software updates compliancy checks, why have you decided to go for PowerShell and not for Configuration Items + Baseline in SCCM 2012 ( I assume you have SCCM since you a querying the SCCM client).
    Greatz my friend !

    Liked by 1 person

    1. We use SCCM for a similar kind of report (based on our patch baseline), but we wanted to query the clients directly as well, to be able to compare the two. If the results were different it would be an indication that something was wrong with either the client or the SCCM reports. I like to be proactive 🙂

      Liked by 1 person

Leave a comment