Here is part two of our tips on PowerShell arrays.
Lets explore some common caveats with arrays, starting with the most important one: before you can take full advantage of array capabilities, you must actually have an array. Relying on PowerShell to automatically deliver one can lead to unexpected results. PowerShell only creates an array when there are at least two elements. Heres a practical example to illustrate this issue (keep in mind that it is meant to showcase the array limitation, not as a real-world security solution):
The goal is to create a list of local administrator accounts with a specific name to check whether certain accounts have local privileges. To account for localization issues, the members of the local Administrators group are retrieved using a well-known SID.
PS> Get-LocalGroupMember -SID S-1-5-32-544
Now, simple array filtering is applied to find all user names that contain "Tobias":
# not so good: trusting that user objects are converted to username whenused as stringPS> (Get-LocalGroupMember -SID S-1-5-32-544) -like '*\*Tobias*'DExxxxxx\xxTobiasxxxDExxxxxx\xxxxTobiasxxDExxxxxx\xxTobiasxxxxxxxxx# better: accessing the property that contains the username (.Name)PS> (Get-LocalGroupMember -SID S-1-5-32-544).Name -like '*\*Tobias*'DExxxxxx\xxTobiasxxxDExxxxxx\xxxxTobiasxxDExxxxxx\xxTobiasxxxxxxxxx
This works great, and all the other techniques mentioned in part 1 can be applied, such as determining the number of users found:
PS> (Get-LocalGroupMember -SID S-1-5-32-544) -like '*\*Tobias*' | Measure-Object | Select-Object -ExpandProperty Count3PS> $users = (Get-LocalGroupMember -SID S-1-5-32-544) -like '*\*Tobias*'PS> $users.Count3PS> ((Get-LocalGroupMember -SID S-1-5-32-544) -like '*\*Tobias*').Count3
However, if the group contains exactly one member, PowerShell will not return an array but instead a single user. Since the result is no longer an array, comparison operators behave normally again: they no longer function as filters and instead return $true or $false to indicate whether the comparison succeeded:
PS> (Get-LocalGroupMember -Name test) -like '*\*Tobias*'True
This PowerShell behavior can lead to hard-to-track production errors because your scripts may start behaving unexpectedly when, by accident or as an edge case, a command returns only a single result object.Fortunately, the solution is simple: ask PowerShell to ALWAYS return an array.
If you need to do this inline, directly in your code without using additional variables, use @():
# wrong wayPS> (Get-LocalGroupMember -Name test) -like '*\*Tobias*'True# correct wayPS> @(Get-LocalGroupMember -Name test) -like '*\*Tobias*'DELL7390\TobiasWeltner
If you use variables, explicitly convert your data to [Array] or [Object[]], or assign these types to your variables to implicitly convert them:
# wrong way (no typing, false results)PS> $result = (Get-LocalGroupMember -Name test)PS> $result -like '*\*Tobias*'True# correct ways, explicit conversion variantsPS> $result = (Get-LocalGroupMember -Name test) -as [Array]PS> $result = (Get-LocalGroupMember -Name test) -as [Object[]]PS> $result = [Array](Get-LocalGroupMember -Name test)PS> $result = [Object[]](Get-LocalGroupMember -Name test)# work as expected, regardless of number of resultsPS> $result -like '*\*Tobias*'DELL7390\TobiasWeltner# result is always [Object[]]PS> $result.GetType().FullName System.Object[] # works, implicit conversion variantsPS> [Array]$result = Get-LocalGroupMember -Name testPS> [Object[]]$result = Get-LocalGroupMember -Name test# also work as expected, regardless of number of resultsPS> $result -like '*\*Tobias*'DELL7390\TobiasWeltner# result is always [Object[]]PS> $result.GetType().FullName System.Object[]
Your ultimate PowerShell Cheat Sheet
Unleash the full potential of PowerShell with our handy poster. Whether you're a beginner or a seasoned pro, this cheat sheet is designed to be your go-to resource for the most important and commonly used cmdlets.The poster is available for download and in paper form.
Related links
- ScriptRunner ActionPacks provide ready-to-use PowerShell scripts.
- Try out ScriptRunner here
- ScriptRunner: Book a demo with our product experts