One powerful aspect of PowerShell is that it is a loosely typed language. The advantage to script developers is that they can assign an untyped variable to almost anything. This makes script development faster and usually easier because variable can be assigned to almost anything without having to fully understand the underlying data types.
The Problem
This advantage however is another example of PowerShell giving authors just enough rope to hang themselves! Scripts will seemingly work until an untyped variable is assigned a value that is a type that the script author did not intend (or test).
I recently got caught in this trap when getting the number of items returned from a cmdlet. For this example we’ll get all the processes running and group by the process name which will give us the number of unique process (names) running:
$myProcessArray = Get-Process | Group-Object ProcessName
$myProcessArray.Count
73
In other words, there are 73 processes running (with a unique Process Name).
The trouble comes in cases where the $myProcessArray is manipulated so that only ONE ITEM IS RETURNED and assigned to a new array. In this case, PowerShell will NOT return 1 (item in the new array). Because there is only 1 item returned, PowerShell will usually consider this an object (in the case a System.Diagnostics.Process object) and return the number of properties instead of array items.
The Solution
The best way to avoid problems such as this is to adopt the best practice of strongly typing the output variable to the type we are expecting – in this case, an array. We do this by wrapping enclosing the script that generates the data with the “@” symbol which forces it into an array like this:
$myProcessArray = @{Get-Process | Group-Object ProcessName}
By forcing the output variable to be an array, it will always be treated like one and the Count property will accurately reflect the number of elements. It will also never be $null.