5

#PSTip ValidatePattern – Friendlier error messages

Note: This tip requires PowerShell 2.0 or above.

PowerShell has a very nice list of built-in parameter validation attributes. They help validating parameter values before any code runs and give end-user consistent pre-configured error messages:

function Test-ValidateSet {
	param (
	    [ValidateSet(
		'Left',
		'Center',
		'Right'
	    )]
	    [string]$Alignment
	)

	"Selected alignment: $Alignment"
}

Test-ValidateSet -Alignment Justify

Test-ValidateSet : Cannot validate argument on parameter 'Alignment'. 
The argument "Justify" does not belong to the set "Left,Center,Right" specified by the ValidateSet attribute. 
Supply an argument that is in the set and then try the command again.

As you can see – I haven’t wrote a single sentence, yet my error message is pretty clear. This is the case for most validators. There is, however, one that produces an error message that for most of us won’t be helpful at all–ValidatePattern:

function Show-UglyError {
	param (
	    [ValidatePattern(
		'^\d{4}-\d{4}$'
	    )]
	    [string]$Puzzle
	)

    "You solved 4-digits hyphen 4-digits puzzle with: $Puzzle!"
}

Show-UglyError -Puzzle Not-A-Solution

Show-UglyError : Cannot validate argument on parameter 'Puzzle'.
The argument "Not-A-Solution" does not match the "^\d{4}-\d{4}$" pattern. 
Supply an argument that matches "^\d{4}-\d{4}$" and try the command again.

As Joel “Jaykul” Bennett pointed out in his blog post on the same topic, for a “normal” user (a person who is not fluent in regular expressions) this error message looks like “Cannot validate argument on parameter ‘Puzzle’. The argument “Not-A-Solution” does not match … yadda, yadda.” Joel’s solution is to build your own, custom ValidatePatternEx class, that derives from ValidateEnumeratedArgumentsAttribute and overrides ValidateElement method. As much as I love this idea, I can see situations when someone may look for something easier and I would like to suggest a different approach: using regular expression comments:

function Show-FriendlyError {
	param (
    		[ValidatePattern(
        		'(?# 4 digits hyphen 4 digits)^\d{4}-\d{4}$'
    		)]
    		[string]$AlmostEasy
	)

	"You guessed it right: $AlmostEasy"
}

Show-FriendlyError -AlmostEasy Wrong!

Show-FriendlyError : Cannot validate argument on parameter 'AlmostEasy'. 
The argument "Wrong!" does not match the "(?# 4 digits hyphen 4 digits)^\d{4}-\d{4}$" pattern. 
Supply an argument that matches "(?# 4 digits hyphen 4 digits)^\d{4}-\d{4}$" and try the command again.

The used pattern has two parts: first part is our comment that may give end-user more clue on how good pattern would look like: ‘(?# Any description you want to give to user)’. Second part (after closing bracket) is pattern that PowerShell will use to validate input, so it contains actual regular expression.
Maybe not perfect, but still easier than original and the implementation cost is very low.

Filed in: Columns, Tips and Tricks Tags: , ,

One Pingback/Trackback

5 Responses to "#PSTip ValidatePattern – Friendlier error messages"

  1. Rob Campbell says:

    Nice solution for regex validation.
    For validation scripts in general, since the error message is going to display the validation script block, you can include helpful information by putting comment line in the validation script block, and it will be displayed in the error message.

    • For ValidateScript your best option may be just throw-ing cumstom message. :)
      function Boom {
      param (
      [ValidateScript({
      throw "Ha! Default value is perfect! Why change it???"
      })]
      [string]$Bam = 'Perfect!'
      )
      "It's $Bam!"
      }

      If you would try it with any parameter passed:
      Boom -Bam Awesome
      Boom : Cannot validate argument on parameter 'Bam'. Ha! Default value is perfect! Why change it???

  2. Other says:

    param(

    [String]$parameter = $(throw “parameter must be specified.”)

    )

    This is a pretty tricky way to have a default parameter.

    • I would stay it’s v1 mandatory parameter… And currently: “force” mandatory parameter (unlike [Parameter(Mandatory)]), it won’t prompt, it will fail. ;) But yes, this technique is pretty cool. :)

Leave a Reply

Submit Comment

© 2014 PowerShell Magazine. All rights reserved. XHTML / CSS Valid.
Proudly designed by Theme Junkie.
%d bloggers like this: