PowerShell Parameter Validation: Building a Better ValidatePattern with ValidateScript
Let's start out by taking a look at what the PowerShell built-in help says about the
ValidatePattern
and ValidateScript
validation attributes:
Here's what that help topic says about ValidatePattern
:
We'll test using ValidatePattern
with an example that I used in my entry for advanced event #4 in
the Script Games this year as shown in the following example:
1function Test-ValidatePattern {
2
3 [CmdletBinding()]
4 param(
5 [Parameter(Mandatory)]
6 [ValidatePattern("^(?!^(PRN|AUX|CLOCK\$|NUL|CON|COM\d|LPT\d|\..*)(\..+)?$)[^\x00-\x1f\\?*:\"";|/]+\.html?$")]
7 [string]$FileName
8 )
9
10 Write-Output $FileName
11
12}
Who knows what that regular expression does? The guy who wrote this might, but probably no one else, especially not the junior level administrators or help desk staff who will be using this tool once it's finished.
One of the feedback comments I received on that particular scripting games entry was "I wish I knew
what this regular expression did ?". The problem with the error messages that are generated by
ValidatePattern
is they tell you that your input didn't match the regular expression. How many
tool users do you know who read regular expressions? Not many unless the tool user is also the
toolmaker. They prefer error messages in their native language (English in the case of my tool
users).
Based on the error message in the screenshot below, my junior level administrators and help desk staff will have no idea what they did wrong, nor will they know what to do to correct the problem if they receive this error:
1The argument “con.html” does not match the
2“^(?!^(PRN|AUX|CLOCK$|NUL|CON|COMd|LPTd|..*)(..+)?$)[^
3x00-x1f\?*:”;|/]+.html?$” pattern. Supply an argument that matches
4“^(?!^(PRN|AUX|CLOCK$|NUL|CON|COMd|LPTd|..*)(..+)?$)[^x00-
5x1f\?*:”;|/]+.html?$” and try the command again.
ValidateScript
to the rescue! Here's what the help says about ValidateScript:
This might be a little more work, but trust me, it will save you a lot of support calls and emails down the road when someone else tries to use this tool and receives the parameter validation error message.
1function Test-ValidateScript {
2
3 [CmdletBinding()]
4 param (
5 [Parameter(Mandatory)]
6 [ValidateScript({
7 If ($_ -match "^(?!^(PRN|AUX|CLOCK\$|NUL|CON|COM\d|LPT\d|\..*)(\..+)?$)[^\x00-\x1f\\?*:\"";|/]+\.html?$") {
8 $True
9 }
10 else {
11 Throw "$_ is either not a valid filename for an HTML file or it is not recommended. See this MSDN article for more information: http://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx#naming_conventions"
12 }
13 })]
14 [string]$FileName
15 )
16
17 Write-Output $FileName
18
19}
1Test-ValidateScript : Cannot validate argument on parameter 'FileName'. con.html is
2either not a valid filename for an HTML file or it is not recommended. See this MSDN
3article for more information: https://msdn.microsoft.com/en-us/library/windows/desktop/aa3
465247(v=vs.85).aspx#naming_conventions
While this may not be the best error message in the world, any error message is better than the one
previously returned by the ValidatePattern
validation attribute.
µ