Quantcast
Channel: Windows PowerShell - SAPIEN Blog
Viewing all articles
Browse latest Browse all 308

Parameter validation affects parameter variables

$
0
0

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.

EdiPrinz

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 juneb@sapien.com or follow her on Twitter at @juneb_get_help.

 
[Google+] [Twitter] [Facebook] [LinkedIn] [StumbleUpon] [Digg] [Reddit] [Google Bookmark]

Viewing all articles
Browse latest Browse all 308

Trending Articles