PowerShell SCCM 2007 Module - My contribution

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-module Andre 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 the Get-WmiObject queries.
Those modifications are now part of the module.

Here is an example :
# 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  `
                    -Namespace "root\sms\site_" `
                    -Class "SMS_R_System" | where-object { $_.ResourceID -eq  }}

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_System and 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!
# 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  `
                    -Namespace "root\sms\site_" `
                    -Query "Select * From SMS_R_System WHERE 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 ALWAYSS try 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.


Thanks for Reading! If you have any questions, leave a comment or send me an email at fxcat@lazywinadmin.com. I invite you to follow me on Twitter: @lazywinadm

1 comment:

  1. Hi. I've been taking a look at Andre Bocchini's automation tools and see so much potential for me. I have a question you might be able to answer. I'm using the Get-SCCMDistributionList cmdlet and passing -siteprovider & -sitecode arguments to it but it seems to only work for Primary sites as secondary sites don't have a root\sms repository. My goal is to be able to remove a package from a number of sites. I wonder can you help?