{"id":8716,"date":"2015-02-11T06:00:00","date_gmt":"2015-02-11T14:00:00","guid":{"rendered":"http:\/\/www.sapien.com\/blog\/?p=8716"},"modified":"2015-02-11T06:21:44","modified_gmt":"2015-02-11T14:21:44","slug":"parameter-validation-affects-parameter-variables","status":"publish","type":"post","link":"https:\/\/dev.sapien.com\/blog\/2015\/02\/11\/parameter-validation-affects-parameter-variables\/","title":{"rendered":"Parameter validation affects parameter variables"},"content":{"rendered":"<p><a class=\"twitter-follow-button\" href=\"https:\/\/twitter.com\/juneb_get_help\" data-lang=\"en\">Follow @juneb_get_help<\/a><\/p>\n<p>In a Google+ discussion this week, <a href=\"https:\/\/plus.google.com\/+EdiPrinz\/posts\">Edi Prinz<\/a> demonstrated an effect of the <strong>ValidationRange<\/strong> parameter attribute that surprised many of us. When you validate a parameter value, the validation rules are enforced on the parameter variable &#8212; and that enforcement persists on the variable for the entire function scope.<\/p>\n<p><a href=\"http:\/\/www.sapien.com\/blog\/wp-content\/uploads\/2015\/02\/EdiPrinz.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-medium wp-image-8765\" src=\"http:\/\/www.sapien.com\/blog\/wp-content\/uploads\/2015\/02\/EdiPrinz-276x300.png\" alt=\"EdiPrinz\" width=\"276\" height=\"300\" srcset=\"https:\/\/dev.sapien.com\/blog\/wp-content\/uploads\/2015\/02\/EdiPrinz-276x300.png 276w, https:\/\/dev.sapien.com\/blog\/wp-content\/uploads\/2015\/02\/EdiPrinz.png 356w\" sizes=\"auto, (max-width: 276px) 100vw, 276px\" \/><\/a><\/p>\n<p>For example, this function has a Value parameter. It uses the <b>ValidateRange<\/b> parameter attribute to allow only parameter values between 3 and 8, inclusive.<\/p>\n<pre lang=\"PowerShell\">function Test-Validation {\r\n    Param (\r\n        [ValidateRange(3,8)]\r\n        [Int32]\r\n        $Value\r\n    )\r\n\r\n    $Value = 3 * $Value\r\n    $Value\r\n}<\/pre>\n<p>Let&#8217;s call the function with a value of 4 (between 3 and 8) for the parameter.<\/p>\n<pre class=\"output\">Test-Validation \u2013Value 4\r\n\r\n<span style=\"color: #ff0000;\">The variable cannot be validated because the value \r\n12 is not a valid value for the Value variable.\r\nAt C:\\ps-test\\Test-ParameterValidation.ps1:7 char:5\r\n+     $Value = 3 * $Value\r\n+     ~~~~~~~~~~~~~~~~~~~\r\n    + CategoryInfo          : MetadataError: (:) [], ValidationMetadataException\r\n    + FullyQualifiedErrorId : ValidateSetFailure<\/span>\r\n\r\n4\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p>What&#8217;s happening here? Why is there an error when the Value parameter has a value of 4?<\/p>\n<p>When you call the Test-Validation function with a value of 2 for the Value parameter, it returns a parameter validation error (&#8220;Cannot validate argument on parameter&#8230;&#8221;), as expected, because a parameter value of 2 is not between 3 and 8 inclusive.<\/p>\n<pre class=\"output\">PS C:\\ps-test&gt; Test-Validation -Value 2\r\n\r\n<span style=\"color: #ff0000;\">Test-Validation : Cannot validate argument on parameter 'Value'. \r\nThe 2 argument is less than the minimum allowed range of 3. \r\nSupply an argument that is greater than or equal to 3 and then try the command again.\r\nAt line:1 char:24\r\n+ Test-Validation -Value 2\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 ~\r\n+ CategoryInfo\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 : InvalidData: (:) [Test-Validation], \r\nParameterBindingValidationException\r\n+ FullyQualifiedErrorId : ParameterArgumentValidationError,Test-Validation<\/span><\/pre>\n<p>&nbsp;<\/p>\n<p>When you enter a parameter value that&#8217;s within the allowed range (such as 4), you don&#8217;t get a <em>parameter<\/em> validation error. Instead, the command that saves the product of &#8220;3 * $Value&#8221; (12) in the $Value variable causes a <em>variable<\/em> validation error (&#8220;&#8230;variable cannot be validated&#8230;&#8221;) error because 12 is not between 3 and 8 inclusive.<\/p>\n<pre lang=\"PowerShell\">$Value = 3 * $Value<\/pre>\n<p>The <em>variable<\/em> value failed the range test, even though the <em>parameter<\/em> value satisfied it. Notice that the final $Value command returns a value of 4, because the command to assign a value of 12 failed.<\/p>\n<pre class=\"output\">PS C:\\ps-test&gt; Test-Validation -Value 4\r\n<span style=\"color: #ff0000;\">The variable cannot be validated because the \r\nvalue 12 is not a valid value for the Value variable.\r\nAt C:\\ps-test\\Test-Validation.ps1:11 char:2\r\n+\u00a0\u00a0\u00a0\u00a0 $Value = 3 * $Value\r\n+\u00a0\u00a0\u00a0\u00a0 ~~~~~~~~~~~\r\n+ CategoryInfo\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 : MetadataError: (:) [], ValidationMetadataException\r\n+ FullyQualifiedErrorId : ValidateSetFailure<\/span>\r\n\r\n4\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p>Surprisingly, the validation that we set on the Value parameter is enforced on the $Value variable, even though we didn&#8217;t set any validation on the variable.<\/p>\n<p>Let&#8217;s see why it happens, when it happens, and how to fix it.<\/p>\n<p>&nbsp;<\/p>\n<h2>Why: Parameters and parameter variables<\/h2>\n<p>Why does this happen?<\/p>\n<p>In Windows PowerShell, function parameters are automatically converted to variables so you can use them in function commands. For example, the <strong>-Value<\/strong> parameter automatically becomes a <strong>$Value<\/strong> variable. If Windows PowerShell didn&#8217;t do this for you, you might need to save the parameter value in local variable explicitly.<\/p>\n<pre lang=\"PowerShell\">function Get-Triple\r\n{\r\n    Param ([Int32]$Value)\u00a0\u00a0 #&lt;-\u2014 This parameter...\r\n\r\n    $Value = 3 * $Value\u00a0\u00a0\u00a0\u00a0 #&lt;\u2014- becomes this variable.\r\n}<\/pre>\n<p>&nbsp;<\/p>\n<p>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&#8217;s fine. Most of the time. But not when you&#8217;re using parameter validation attributes.<\/p>\n<p>&nbsp;<\/p>\n<h2>Where: What&#8217;s the scope of this effect?<\/h2>\n<p>Windows PowerShell applies parameter validation to the parameter variable in the script.<\/p>\n<ul>\n<li>Affects all Validate* attributes, such as <strong>ValidateSet<\/strong> and <strong>ValidatePattern<\/strong>, but not other attributes, such as Allow.<\/li>\n<li>Occurs in Windows PowerShell 2.0 and later. (In the Google+ discussion, you&#8217;ll see mentions of 4.0 and 3.0 in the Google+ conversation, but it happens in 2.0, too.)<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<h2>How to override the validation<\/h2>\n<p>Now that we know the effect, it&#8217;s easy to avoid an error.<\/p>\n<ul>\n<li>Create a new variable and use the new variable in the calculations.For example, in this function, we create a second variable called $NewValue.<\/li>\n<\/ul>\n<pre lang=\"PowerShell\">function Test-Validation {\r\n    Param (\r\n        [ValidateRange(3,8)]\r\n        [Int32]\r\n        $Value)\r\n\r\n    $NewValue = 3 * $Value\r\n    $NewValue\r\n}<\/pre>\n<ul>\n<ul>\n<li>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).<br \/>\nWhen you use ValidateRange to set a range of 0 &#8211; 9999 for the $Value variable, this function now runs without error.<\/li>\n<\/ul>\n<\/ul>\n<pre lang=\"PowerShell\">function Test-Validation {\r\n    Param (\r\n        [ValidateRange(3,8)]\r\n        [Int32]\r\n        $Value)\r\n\r\n    [ValidateRange(0, 9999)]$Value = 3 * $Value\r\n    $Value\r\n}<\/pre>\n<pre class=\"output\">Test-Validation -Value 4\r\n12<\/pre>\n<p>But, to fix the problem, you have to know that it exists.<\/p>\n<p>Many thanks to Edi Prinz for pointing this out and for filing a <a href=\"https:\/\/connect.microsoft.com\/PowerShell\/Feedback\/Details\/1117495\" target=\"_blank\">Connect documentation bug<\/a> against the about_Functions_Advanced_Parameters help topic. I voted up the bug. Hope you do, too.<\/p>\n<p><em>June Blender is a technology evangelist at SAPIEN Technologies, Inc. You can reach her at <\/em><a href=\"mailto:juneb@sapien.com\"><em>juneb@sapien.com<\/em><\/a><em> or follow her on Twitter at <\/em><a href=\"https:\/\/twitter.com\/juneb_get_help\"><em>@juneb_get_help<\/em><\/a><em>.<\/em><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Follow @juneb_get_help 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 &#8212; and that enforcement persists on the variable for the entire function scope. For example, this function [&hellip;]<\/p>\n","protected":false},"author":31,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"footnotes":""},"categories":[25],"tags":[934,28],"class_list":["post-8716","post","type-post","status-publish","format-standard","hentry","category-windows-powershell","tag-juneb","tag-powershell"],"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/dev.sapien.com\/blog\/wp-json\/wp\/v2\/posts\/8716","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/dev.sapien.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/dev.sapien.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/dev.sapien.com\/blog\/wp-json\/wp\/v2\/users\/31"}],"replies":[{"embeddable":true,"href":"https:\/\/dev.sapien.com\/blog\/wp-json\/wp\/v2\/comments?post=8716"}],"version-history":[{"count":53,"href":"https:\/\/dev.sapien.com\/blog\/wp-json\/wp\/v2\/posts\/8716\/revisions"}],"predecessor-version":[{"id":8773,"href":"https:\/\/dev.sapien.com\/blog\/wp-json\/wp\/v2\/posts\/8716\/revisions\/8773"}],"wp:attachment":[{"href":"https:\/\/dev.sapien.com\/blog\/wp-json\/wp\/v2\/media?parent=8716"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/dev.sapien.com\/blog\/wp-json\/wp\/v2\/categories?post=8716"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/dev.sapien.com\/blog\/wp-json\/wp\/v2\/tags?post=8716"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}