2 minute read

I recently contributed to a PowerShell module called SCCM Automation created by Andre Bocchini. (SCCM stands for System Center Configuration Manager)

Take a look at it on GitHub here:https://github.com/andrebocchini/sccm-powershell-automation-moduleAndre really did an awesome job on this module!

This Module for SCCM 2007 (which does not come with a set of PowerShell Cmdlets) allows you to query Computers, Collections, Advertisements etc… (Check the Full list of Cmdlets)

However against big SCCM environment I notice some functions queries were very slow to report object. After inspecting the code, I tweaked some parts of the code, especially on theGet-WmiObject queries. Those modifications are now part of the module.

Here is an example :</u>

# In the module we have the following query 
#  (I had Backtick to fit in my blog, don't do this at home! ;-) )
$computer =  Get-WMIObject `
                  -ComputerName $siteProvider `
                  -Namespace "root\sms\site_$siteCode" `
                  -Class "SMS_R_System" | Where { $_.ResourceID -eq $resourceId }
  
# Let's measure our command on a big environment (+6000 computers)
#  Note that I replaced some values, you need to specify the SiteProvider, SiteCode and 
#  ResourceID.
Measure-Command {Get-WMIObject`
                    -ComputerName <SiteProvider> `
                    -Namespace "root\sms\site_<SITECODE>" `
                    -Class "SMS_R_System" | where-object { $_.ResourceID -eq <ResourceID> }}


Days              : 0
Hours             : 0
Minutes           : 0
Seconds           : 42
Milliseconds      : 273
Ticks             : 422735527
TotalDays         : 0.000489277230324074
TotalHours        : 0.0117426535277778
TotalMinutes      : 0.704559211666667
TotalSeconds      : 42.2735527
TotalMilliseconds : 42273.5527

It took 42 seconds to finish this command, that’s pretty long… Basically the command has to gather ALLLLLL the objects from the class SMS_R_Systemand then send it throught the pipe to Where-Object to filter on the ResourceID property.

Let's try to improve this and use some filtering! </u>


# Let's measure our command on a big environment (+6000 computers) with some filtering
#  Note that I replaced some values, you need to specify the SiteProvider, SiteCode and 
#  ResourceID.
Measure-Command {Get-WMIObject`
                    -ComputerName <SiteProvider> `
                    -Namespace "root\sms\site_<SITECODE>" `
                    -Query "Select * From SMS_R_System WHERE ResourceID='<ResourceID>'"}
                    
Days              : 0
Hours             : 0
Minutes           : 0
Seconds           : 0
Milliseconds      : 202
Ticks             : 2026858
TotalDays         : 2.34590046296296E-06
TotalHours        : 5.63016111111111E-05
TotalMinutes      : 0.00337809666666667
TotalSeconds      : 0.2026858
TotalMilliseconds : 202.6858

WOW! This time Only 200 Milliseconds!! Pretty Awesome! Filtering is definitely the way to go! ;-)
All I did is really filtering on the ResourceID property with Get-WmiObject, I don’t need to retrieve all the data.

In Powershell you should Always Always Always ALWAYSStry to filter before sending the output to the pipeline, and this apply to all the Cmdlets… This was well resumed by the Scripting Guy, Ed Wilson [Top Ten PowerShell Best Practices]:

Filter on the left. It is more efficient to filter returning data as close to the source of data as possible. For example, you do not want to return the entire contents of the system event log across the network to your work station, and then filter events for a specific event ID. Instead, you want to filter the system event log on the server, and then return the data.

Resources

Leave a comment