3 min read
Typed PowerShell Arrays and Generic Lists
Understanding the different array types in PowerShell is essential for efficient data management and automation in your...
Unlocking the Power of PowerShell: Tips for Success
Here is part two of our tips on PowerShell arrays.
Let’s 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. Here’s 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 when
used as string
PS> (Get-LocalGroupMember -SID S-1-5-32-544) -like '*\*Tobias*'
DExxxxxx\xxTobiasxxx
DExxxxxx\xxxxTobiasxx
DExxxxxx\xxTobiasxxxxxxxxx
# better: accessing the property that contains the username (.Name)
PS> (Get-LocalGroupMember -SID S-1-5-32-544).Name -like '*\*Tobias*'
DExxxxxx\xxTobiasxxx
DExxxxxx\xxxxTobiasxx
DExxxxxx\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 Count
3
PS> $users = (Get-LocalGroupMember -SID S-1-5-32-544) -like '*\*Tobias*'
PS> $users.Count
3
PS> ((Get-LocalGroupMember -SID S-1-5-32-544) -like '*\*Tobias*').Count
3
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 way
PS> (Get-LocalGroupMember -Name test) -like '*\*Tobias*'
True
# correct way
PS> @(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 variants
PS> $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 results
PS> $result -like '*\*Tobias*'
DELL7390\TobiasWeltner
# result is always [Object[]]
PS> $result.GetType().FullName
System.Object[]
# works, implicit conversion variants
PS> [Array]$result = Get-LocalGroupMember -Name test
PS> [Object[]]$result = Get-LocalGroupMember -Name test
# also work as expected, regardless of number of results
PS> $result -like '*\*Tobias*'
DELL7390\TobiasWeltner
# result is always [Object[]]
PS> $result.GetType().FullName
System.Object[]
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.
Jan 28, 2025 by Aleksandar Nikolić and Dr. Tobias Weltner
Understanding the different array types in PowerShell is essential for efficient data management and automation in your...
Jan 21, 2025 by Aleksandar Nikolić and Dr. Tobias Weltner
Optimizing PowerShell arrays is key to improving script performance and ensuring efficient data handling in your...
Jan 16, 2025 by Aleksandar Nikolić and Dr. Tobias Weltner
Here is part two of our tips on PowerShell arrays.
Let’s explore some common caveats with arrays, starting with the...
Tobias Weltner and Aleksandar Nikolić joinly wrote the blog post series 'Tobias&Aleksandar's PowerShell tips'. So we introduce both of them here:
----------------------------
Aleksandar Nikolić is a Microsoft Azure MVP and co-founder of PowerShellMagazine.com, the ultimate online source for PowerShell enthusiasts. With over 18 years of experience in system administration, he is a respected trainer and speaker who travels the globe to share his knowledge and skills on Azure, Entra, and PowerShell. He has spoken at IT events such as Microsoft Ignite, ESPC, NIC, CloudBrew, NTK, and PowerShell Conference Europe.
----------------------------
Tobias is a long-time Microsoft MVP and has been involved with the development of PowerShell since its early days. He invented the PowerShell IDE "ISESteroids", has written numerous books on PowerShell for Microsoft Press and O'Reilly, founded the PowerShell Conference EU (psconf.eu), and is currently contributing to the advancement of PowerShell as member in the "Microsoft Cmdlet Working Group". Tobias shares his expertise as a consultant in projects and as a trainer in in-house trainings for numerous companies and agencies across Europe.