Star InactiveStar InactiveStar InactiveStar InactiveStar Inactive
 

In a Google+ discussion this week, Edi Prinz demonstrated an effect of the ValidationRange parameter attribute that surprised many of us. When you validate a parameter value, the validation rules are enforced on the parameter variable — and that enforcement persists on the variable for the entire function scope.

Edi Prinz

For example, this function has a Value parameter. It uses the ValidateRange parameter attribute to allow only parameter values between 3 and 8, inclusive.

function Test-Validation {
    Param (
        [ValidateRange(3,8)]
        [Int32]
        $Value
    )
 
    $Value = 3 * $Value
    $Value
}

Let’s call the function with a value of 4 (between 3 and 8) for the parameter.

Test-Validation –Value 4

The variable cannot be validated because the value 
12 is not a valid value for the Value variable.
At C:\ps-test\Test-ParameterValidation.ps1:7 char:5
+     $Value = 3 * $Value
+     ~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : MetadataError: (:) [], ValidationMetadataException
    + FullyQualifiedErrorId : ValidateSetFailure

4

 

What’s happening here? Why is there an error when the Value parameter has a value of 4?

When you call the Test-Validation function with a value of 2 for the Value parameter, it returns a parameter validation error (“Cannot validate argument on parameter…”), as expected, because a parameter value of 2 is not between 3 and 8 inclusive.

PS C:\ps-test> Test-Validation -Value 2

Test-Validation : Cannot validate argument on parameter 'Value'. 
The 2 argument is less than the minimum allowed range of 3. 
Supply an argument that is greater than or equal to 3 and then try the command again.
At line:1 char:24
+ Test-Validation -Value 2
+                        ~
+ CategoryInfo          : InvalidData: (:) [Test-Validation], 
ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationError,Test-Validation

 

When you enter a parameter value that’s within the allowed range (such as 4), you don’t get a parameter validation error. Instead, the command that saves the product of “3 * $Value” (12) in the $Value variable causes a variable validation error (“…variable cannot be validated…”) error because 12 is not between 3 and 8 inclusive.

$Value = 3 * $Value

The variable value failed the range test, even though the parameter value satisfied it. Notice that the final $Value command returns a value of 4, because the command to assign a value of 12 failed.

PS C:\ps-test> Test-Validation -Value 4
The variable cannot be validated because the 
value 12 is not a valid value for the Value variable.
At C:\ps-test\Test-Validation.ps1:11 char:2
+     $Value = 3 * $Value
+     ~~~~~~~~~~~
+ CategoryInfo          : MetadataError: (:) [], ValidationMetadataException
+ FullyQualifiedErrorId : ValidateSetFailure

4

 

Surprisingly, the validation that we set on the Value parameter is enforced on the $Value variable, even though we didn’t set any validation on the variable.

Let’s see why it happens, when it happens, and how to fix it.

 

Why: Parameters and parameter variables

Why does this happen?

In Windows PowerShell, function parameters are automatically converted to variables so you can use them in function commands. For example, the -Value parameter automatically becomes a $Value variable. If Windows PowerShell didn’t do this for you, you might need to save the parameter value in local variable explicitly.

function Get-Triple
{
    Param ([Int32]$Value)   #<-— This parameter...
 
    $Value = 3 * $Value     #<—- becomes this variable.
}

 

But, in the Test-Validation function script block, we forgot about the parameter-ness of this parameter variable and just thought of it as a variable. And that’s fine. Most of the time. But not when you’re using parameter validation attributes.

 

Where: What’s the scope of this effect?

Windows PowerShell applies parameter validation to the parameter variable in the script.

  • Affects all Validate* attributes, such as ValidateSet and ValidatePattern, but not other attributes, such as Allow.
  • Occurs in Windows PowerShell 2.0 and later. (In the Google+ discussion, you’ll see mentions of 4.0 and 3.0 in the Google+ conversation, but it happens in 2.0, too.)

 

How to override the validation

Now that we know the effect, it’s easy to avoid an error.

  • Create a new variable and use the new variable in the calculations.For example, in this function, we create a second variable called $NewValue.
function Test-Validation {
    Param (
        [ValidateRange(3,8)]
        [Int32]
        $Value)
 
    $NewValue = 3 * $Value
    $NewValue
}
    • Beginning in Windows PowerShell 3.0, you can use the Validation attributes on variables, so you can set a new validation range on the parameter variable (or any other variable).
      When you use ValidateRange to set a range of 0 – 9999 for the $Value variable, this function now runs without error.
function Test-Validation {
    Param (
        [ValidateRange(3,8)]
        [Int32]
        $Value)
 
    [ValidateRange(0, 9999)]$Value = 3 * $Value
    $Value
}
Test-Validation -Value 4
12

But, to fix the problem, you have to know that it exists.

Many thanks to Edi Prinz for pointing this out and for filing a Connect documentation bug against the about_Functions_Advanced_Parameters help topic. I voted up the bug. Hope you do, too.

June Blender is a technology evangelist at SAPIEN Technologies, Inc. You can reach her at This email address is being protected from spambots. You need JavaScript enabled to view it. or follow her on Twitter at @juneb_get_help.

If you have questions about our products, please post in our support forum.
For licensed customers, use the forum associated with your product in our Product Support Forums for Registered Customers.
For users of trial versions, please post in our Former and Future Customers - Questions forum.
Copyright © 2024 SAPIEN Technologies, Inc.