4 min read
Understanding PowerShell Arrays
PowerShell arrays are a powerful and versatile way of managing collections of data, enabling you to efficiently...
Unlocking the Power of PowerShell: Tips for Success
Tired of hidden errors in your PowerShell scripts? Discover how validation and transformation attributes can bring precision and automation to your code!
When you assign information to variables, PowerShell, by default, doesn’t do any extra work. It simply takes the value and stores it in the variable:
$test = '1.2.3.4'
$test
While convenient, this can mask errors in larger scripts and make debugging more difficult. If desired, you can ask PowerShell to invoke type conversions, run entire script blocks to validate and transform variable assignments, and emit errors when invalid data is encountered.
By assigning a type to a variable, any new value assigned to it must be of that type, or be convertible to it. If invalid values cannot be converted, an exception is raised:
[int]$id = 123
$id = 12.5
$id # now 12 (rounded)
$id = 'wrong' # raises an error, not convertible to int
Type assignments offer another great benefit: they allow you to select a more suitable type for your data, which can save you a lot of work. Take a look at this example:
$installed = '2.3.4.5'
$available = '10.1.2.3'
$shouldInstall = $installed -lt $available
$shouldInstall
Since PowerShell uses alphanumeric comparison for strings, "2.3.4.5" is considered greater than "10.1.2.3". You would need to invest significant effort to compare the numbers individually.
Alternatively, you can delegate this task to a more suitable type: once you assign the variables to the "[version]" type, they are compared correctly.
[version]$installed = '2.3.4.5'
[version]$available = '10.1.2.3'
$shouldInstall = $installed -lt $available
$shouldInstall
Sometimes, there is no perfectly matching type for your data. In such cases, you can use a base type and refine it with a validation attribute.
For example, if you want a variable to store an ID number in the range of 1 to 1000 and be notified (via an exception) when an invalid ID number is encountered, you could use [int] as the base type and add [ValidateRange(1, 1000)]:
[ValidateRange(1,1000)][int]$id = 10
# this works
$id = 1000
# this raises exception
$id = -1
$id = 1001
There are several built-in validation attributes; however, [ValidateScript()] is the most flexible, as it allows you to define the validation criteria yourself.
Here’s an example of a variable that can only store file paths to files that actually exist in your Windows folder:
[ValidateScript({ Test-Path -Path $_ -PathType Leaf})][string]$filepath = 'C:\Windows\explorer.exe'
# this works
$filepath = "$env:windir\notepad.exe"
# this fails
$filepath = "c:\test.txt"
By adding transformation attributes, you can instruct a variable on how to interpret an assignment and convert it into any form or shape you desire.
Here’s an example of a custom transformation attribute:
class ServerIdAttribute : System.Management.Automation.ArgumentTransformationAttribute
{
[object]
Transform([System.Management.Automation.EngineIntrinsics]$engineIntrinsics, [object] $inputData)
{
################## Start of custom code ##################################
# variable assignment is found in $inputData
# user input was already a well-formed server name
if ($inputData -match '^Server\d{4}$')
{
return $inputData
}
# user input was a number, construct server name
elseif ($inputData -is [int])
{
return 'Server{0:d4}' -f $inputData
}
# user input was a string, can it be converted to a number?
elseif ($inputData -as [int])
{
return 'Server{0:d4}' -f ($inputData -as [int])
}
# invalid user input
else
{
throw "Server names must be 'ServerXXXX' where 'XXXX' is a number."
}
################## End of custom code ###################################
}
}
This template remains the same; only the code between the markings changes, determining how $inputData (the assignment) should be converted before being stored in the variable.
The class name defines the name of your transformation attribute and must always end with 'Attribute.' In this example, the class name is ServerIdAttribute, so the transformation attribute is named [ServerId()].
Once you have defined this attribute, you can assign variables like this:
[ServerId()]$serverName = 12
The variable now contains 'Server0012'. Since variables retain their types and attributes, whenever you assign a number to the variable, it will automatically generate a server name with a four-digit number:
PS C:\> $serverName
Server0999
PS C:\> $serverName = "98"
PS C:\> $serverName
Server0098
PS C:\> $serverName = 'Server0123'
PS C:\> $serverName
Server0123
Transformation attributes remain active throughout the lifetime of a variable. Whenever new values are assigned, the code inside the transformation attribute is executed.
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 7, 2025 by Aleksandar Nikolić and Dr. Tobias Weltner
PowerShell arrays are a powerful and versatile way of managing collections of data, enabling you to efficiently...
Dec 27, 2024 by Aleksandar Nikolić and Dr. Tobias Weltner
Tired of hidden errors in your PowerShell scripts? Discover how validation and transformation attributes can bring...
Dec 20, 2024 by Aleksandar Nikolić and Dr. Tobias Weltner
Want to make your PowerShell scripts faster and more flexible? Learn how to optimize the pipeline with script blocks...
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.