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 {
 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  )
10  Write-Output $FileName

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
3x00-x1f\?*:”;|/]+.html?$” pattern. Supply an argument that matches
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 {
 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  )
17  Write-Output $FileName


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

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.