This blog article is the second in a series of blog articles that is being written on PowerShell advanced functions for PowerShell blogging week. If you haven’t already read the first article in this series: “Standard and Advanced PowerShell functions“ written by PowerShell MVP Francois-Xavier Cat, I recommend reading it also.

What is parameter validation? In PowerShell, parameter validation is the automated testing to validate the accuracy of parameter values passed to a command.

Why validate parameter input? The question should be, can your function complete successfully without valid input being provided? If not, parameter validation should be performed to catch problems early on and before your function performs any actions. There could also be security risks associated with accepting input that isn’t validated.

In this first example, no parameter validation is being performed:

Test-NoValidation function Test-NoValidation { [CmdletBinding()] param ( $FileName ) Write-Output $FileName } 1 2 3 4 5 6 7 function Test-NoValidation { [ CmdletBinding ( ) ] param ( $FileName ) Write-Output $FileName }

This allows any number of values and any value including null, empty, or invalid file names to be provided for the FileName parameter:

There are several different parameter validation attributes that can be used to validate the values that are provided for parameter input.

ValidateLength is one of those attributes. It validates that the number of characters are within a specified range as shown in the following example where the value provided for the FileName parameter must be between one and twelve characters in length:

Test-ValidateLength function Test-ValidateLength { [CmdletBinding()] param ( [ValidateLength(1,12)] [string]$FileName ) Write-Output "$FileName is $($FileName.Length) characters long" } 1 2 3 4 5 6 7 8 function Test-ValidateLength { [ CmdletBinding ( ) ] param ( [ ValidateLength ( 1 , 12 ) ] [ string ] $FileName ) Write-Output "$FileName is $($FileName.Length) characters long" }

Typing the FileName variable as a [string] prevents more than one value from being provided for it as shown in the previous example.

Values outside the specified character length generate an error:

ValidateLength probably isn’t the best parameter validation attribute for validating something like a file name since it allows invalid file name characters to be specified.

ValidatePattern validates the input against a regular expression:

Test-ValidatePattern function Test-ValidatePattern { [CmdletBinding()] param ( [ValidatePattern('^(?!^(PRN|AUX|CLOCK\$|NUL|CON|COM\d|LPT\d|\..*)(\..+)?$)[^\x00-\x1f\\?*:\"";|/]+$')] [string]$FileName ) Write-Output $FileName } 1 2 3 4 5 6 7 8 function Test-ValidatePattern { [ CmdletBinding ( ) ] param ( [ ValidatePattern ( '^(?!^(PRN|AUX|CLOCK\$|NUL|CON|COM\d|LPT\d|\..*)(\..+)?$)[^\x00-\x1f\\?*:\"";|/]+$' ) ] [ string ] $FileName ) Write-Output $FileName }

If the value doesn’t match the regular expression, an error is generated:

As you can see in the previous example, the error messages that ValidatePattern generates are cryptic unless you read regular expressions and since most people don’t, I typically avoid using it. The same type of input validation can be performed using ValidateScript while providing the user of your function with a meaningful error message.

ValidateScript uses a script to validate the value:

Test-ValidateScript function Test-ValidateScript { [CmdletBinding()] param ( [ValidateScript({ If ($_ -match '^(?!^(PRN|AUX|CLOCK\$|NUL|CON|COM\d|LPT\d|\..*)(\..+)?$)[^\x00-\x1f\\?*:\"";|/]+$') { $True } else { Throw "$_ is either not a valid filename or it is not recommended." } })] [string]$FileName ) Write-Output $FileName } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 function Test-ValidateScript { [ CmdletBinding ( ) ] param ( [ ValidateScript ( { If ( $_ -match '^(?!^(PRN|AUX|CLOCK\$|NUL|CON|COM\d|LPT\d|\..*)(\..+)?$)[^\x00-\x1f\\?*:\"";|/]+$' ) { $True } else { Throw "$_ is either not a valid filename or it is not recommended." } } ) ] [ string ] $FileName ) Write-Output $FileName }

Notice the meaningful error message:

ValidateCount limits the number of values that can be provided:

Test-ValidateCount function Test-ValidateCount { [CmdletBinding()] param ( [ValidateCount(2,6)] [string[]]$ComputerName ) Write-Output "The ComputerName array contains $($ComputerName.Count) items." } 1 2 3 4 5 6 7 8 function Test-ValidateCount { [ CmdletBinding ( ) ] param ( [ ValidateCount ( 2 , 6 ) ] [ string [ ] ] $ComputerName ) Write-Output "The ComputerName array contains $($ComputerName.Count) items." }

Typing the variable as a [string[]] allows multiple values to be provided.

Specifying too few or too many values generates an error:

ValidateRange verifies the value is within a specific numeric range:

Test-ValidateRange function Test-ValidateRange { [CmdletBinding()] param ( [ValidateRange(1582,9999)] [int]$Year ) Write-Output "$Year is a valid Gregorian calendar year" } 1 2 3 4 5 6 7 8 function Test-ValidateRange { [ CmdletBinding ( ) ] param ( [ ValidateRange ( 1582 , 9999 ) ] [ int ] $Year ) Write-Output "$Year is a valid Gregorian calendar year" }

Verify the input is between 1582 and 9999:

ValidateSet specifies a specific set of valid values:

Test-ValidateSet function Test-ValidateSet { [CmdletBinding()] param ( [ValidateSet('CurrentUser','LocalMachine')] [string]$StoreLocation ) Write-Output $StoreLocation } 1 2 3 4 5 6 7 8 function Test-ValidateSet { [ CmdletBinding ( ) ] param ( [ ValidateSet ( 'CurrentUser' , 'LocalMachine' ) ] [ string ] $StoreLocation ) Write-Output $StoreLocation }

Beginning with PowerShell version 3, those values will tab expand in the PowerShell console and they’ll show up in intellisense in the PowerShell ISE (Integrated Scripting Environment) and most third party products such as SAPIEN PowerShell Studio.

In the previous examples, the parameters weren’t designated as being mandatory however. This means that they aren’t required to be specified:

Mandatory parameters require the user to provide a value:

Test-ValidateSet #Requires -Version 3.0 function Test-ValidateSet { [CmdletBinding()] param ( [Parameter(Mandatory)] [ValidateSet('CurrentUser','LocalMachine')] [string]$StoreLocation ) Write-Output $StoreLocation } 1 2 3 4 5 6 7 8 9 10 #Requires -Version 3.0 function Test-ValidateSet { [ CmdletBinding ( ) ] param ( [ Parameter ( Mandatory ) ] [ ValidateSet ( 'CurrentUser' , 'LocalMachine' ) ] [ string ] $StoreLocation ) Write-Output $StoreLocation }

If a mandatory parameter isn’t specified, you’re prompted for a value:

Default values can’t be used with mandatory parameters. If a default value is specified with a mandatory parameter and the parameter isn’t specified when calling the function, you’ll still be prompted for a value (the default value will never be used).

ValidateNotNullOrEmpty prevents null or empty values from being provided and default values can be used with this particular validation attribute:

Test-NotNullOrEmpty function Test-NotNullOrEmpty { [CmdletBinding()] param ( [ValidateNotNullOrEmpty()] [string]$ComputerName = $env:COMPUTERNAME ) Write-Output $ComputerName } 1 2 3 4 5 6 7 8 function Test-NotNullOrEmpty { [ CmdletBinding ( ) ] param ( [ ValidateNotNullOrEmpty ( ) ] [ string ] $ComputerName = $env : COMPUTERNAME ) Write-Output $ComputerName }

The default value is used when the parameter isn’t specified:

I’ve demonstrated the more common parameter validation attributes in this blog article, to learn more see the about_Functions_Advanced_Parameters help topic:

help about_Functions_Advanced_Parameters -ShowWindow 1 help about_Functions_Advanced_Parameters -ShowWindow

Be sure to keep an eye on the #PSBlogWeek hash tag on twitter and the PSBlogWeek twitter list that I’ve created to know when each of the additional articles in this series of blog articles are published throughout the remainder of the week.

Also, be sure to take a look at my blog article “The mother of all PowerShell blogs week is coming next week!“ that I published last week to learn who the bloggers are that are participating in PowerShell blogging week.

Update – April 5, 2015

Yesterday was the last day in the PowerShell blogging week series so I thought I would add direct links to all of the articles since it has now concluded.

These articles have been complied into a Free eBook on PowerShell Advanced Functions.

µ

Share this: Twitter

Reddit

LinkedIn

Facebook

Pocket

Print

