Skip to the main content.

Unlocking the Power of PowerShell: Tips for Success

Enhance PowerShell scripts to validate and transform data

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.

 

Assigning type

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 

 

Refining types

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" 

 

Transforming data

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.

 

 

 

Good2know

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.

PowerShell Poster 2023

Get your poster here!

 

 

Related links 

 

Related posts

4 min read

Understanding PowerShell Arrays

PowerShell arrays are a powerful and versatile way of managing collections of data, enabling you to efficiently...

5 min read

Enhance PowerShell scripts to validate and transform data

Tired of hidden errors in your PowerShell scripts? Discover how validation and transformation attributes can bring...

4 min read

Embrace the PowerShell pipeline

Want to make your PowerShell scripts faster and more flexible? Learn how to optimize the pipeline with script blocks...

About the author: