Thursday, January 9, 2014

Filtering left and error trapping in Powershell

The Scripting Games have started and I am pleased to see that a few teams have already published interesting approaches to the first test event. Nonetheless I see that some people still persevere with some of the common mistakes beginners do.

In this blog post, I want to shed some light on two of these common mistakes.

The first one it’s not really a mistake but a bad habit. Let's see why. In the first test event you are asked to perform some quite complex computer inventory tasks. As you know, inventorying Windows-based computers generally passes through WMI queries through the use of the Get-WmiObject cmdlet:
Get-WmiObject–class win32_service  –computername (Get-Content serverlist.txt)
Some people naïvely tend to remove returned objects from the pipeline using Where-Object cmdlet.
But, and this is very important, when you are retrieving many information from many distant servers, and piping the resulting objects to Where-Object, you could encounter performance problems due to the huge amount of data your station has to analyze and keep or discard.
The tip here (that Don Jones named ‘Filter Left’ in his training) is to make use of the –Filter parameter, which is available for many Powershell cmdlets:
Get-Command -ParameterName filter

CommandType     Name
-----------     ----
Cmdlet          Add-Content
Cmdlet          Clear-Content
Cmdlet          Clear-Item
Cmdlet          Clear-ItemProperty
Cmdlet          Copy-Item
Cmdlet          Copy-ItemProperty
Cmdlet          Get-Acl
Cmdlet          Get-ChildItem
Cmdlet          Get-Content
Cmdlet          Get-Item
Cmdlet          Get-ItemProperty
Cmdlet          Get-Job
Cmdlet          Get-WmiObject
Cmdlet          Get-WSManInstance
Cmdlet          Invoke-Item
Cmdlet          Move-Item
Cmdlet          Move-ItemProperty
Cmdlet          New-ItemProperty
Cmdlet          Remove-Item
Cmdlet          Remove-ItemProperty
Cmdlet          Remove-Job
Cmdlet          Rename-ItemProperty
Cmdlet          Resume-Job
Cmdlet          Set-Acl
Cmdlet          Set-Content
Cmdlet          Set-Item
Cmdlet          Set-ItemProperty
Cmdlet          Stop-Job
Cmdlet          Suspend-Job
Cmdlet          Test-Path
Cmdlet          Wait-Job
Using this –Filter parameters boosts your WMI query performance by letting the WMI service itself on the remote server do the homework of filtering information.

A quick script allows us to verify this statement, even on local queries:
$FilterDuration = (Measure-Command -Expression {Get-ChildItem -Path $env:windir\system32 -Filter *.dll}).Milliseconds
$WhereDuration = (Measure-Command -Expression { Get-ChildItem -Path $env:windir\system32 | Where-Object Extension -eq ".dll"}).Milliseconds
"Filtering with -Filter: $FilterDuration ms"
"Filtering with Where-Object: $WhereDuration ms" 

Filtering with -Filter: 239 ms
Filtering with Where-Object: 803 ms 
There you go: unsurprisingly we get 200 milliseconds for –Filter versus more than 800 milliseconds for Where-Object.

Let me move on to the second mistake, which is not knowing that you have to explicitly set the value of the parameter -ErrorAction to Stop in your WMI queries if you want to trap errors using the Try {} construct.

This is because some exceptions returned by WMI queries aren't terminating errors.

For example, the following script returns a big red error message, like if the Catch {} block was skipped:
Try {
    get-wmiobject -class "Win32_PhysicalMemory" -computername Ghostserver
Catch {
    "WMI query failed..."

Get-WmiObject : The RPC server is unavailable. (Exception from HRESULT: 0x800706BA) 
While the following one properly catches the error and shows the predefined error message:
Try {
    get-wmiobject -class "Win32_PhysicalMemory" -computername Ghostserver -ErrorAction Stop
catch {
    "WMI query failed..."
The major advantage of transforming your WMI errors in terminating exceptions and writing to the host nicely composed error messages is that you show that you master your code and that your scripts is designed well enough to cope with unforeseen issues.

Hope this helps.

No comments:

Post a Comment

Related Posts Plugin for WordPress, Blogger...