{"id":10321,"date":"2006-05-09T23:15:00","date_gmt":"2006-05-09T23:15:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/powershell\/2006\/05\/09\/programmatic-way-to-get-valid-string-values-for-a-parameter\/"},"modified":"2019-02-18T13:21:43","modified_gmt":"2019-02-18T20:21:43","slug":"programmatic-way-to-get-valid-string-values-for-a-parameter","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/powershell\/programmatic-way-to-get-valid-string-values-for-a-parameter\/","title":{"rendered":"Programmatic way to get valid string values for a parameter"},"content":{"rendered":"<p>&lt;WIZARD WARNING&gt;&nbsp; <font color=\"#ff0000\"><em>ISVs and Tool vendors may find this important, Advanced users may find this interesting, Casual users may want to skip this.<\/em><\/font><\/p>\n<p>Someone asked me if there was a programmatic way to tell what the legal values for a string parameter to a cmdlet was.&nbsp; The example was OUT-FILE -ENCODING xxx<\/p>\n<p>Out current&nbsp;help doesn&#8217;t tell you this information (and it wouldn&#8217;t be a great programmatic experience even if it did) and neither does Get-Command:<\/p>\n<p><font face=\"Courier New\" color=\"#000080\" size=\"1\">PS&gt; <strong>get-command out-file |fl Definition<\/strong><br \/>Definition : Out-File [-FilePath] &lt;String&gt; <strong><font color=\"#ff0000\">[[-Encoding] &lt;String&gt;]<\/font><\/strong> [-Append]<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [-Force] [-NoClobber] [-Width &lt;Int32&gt;] [-InputObject &lt;PSObjec<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; t&gt;] [-Verbose] [-Debug] [-ErrorAction &lt;ActionPreference&gt;] [-Er<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rorVariable &lt;String&gt;] [-OutVariable &lt;String&gt;] [-OutBuffer &lt;Int<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 32&gt;] [-WhatIf] [-Confirm]<\/font><\/p>\n<p>It tells me that it takes a string but not what the values are.&nbsp; When you try to assign an incorrect value, you&#8217;ll be told what the correct values are:<\/p>\n<p><font face=\"Courier New\" color=\"#0000ff\" size=\"1\">PS&gt; <strong>gps |out-file foo.txt -Encoding UTF-8<br \/><\/strong>Out-File : Cannot validate argument &#8220;UTF-8&#8221; because it does not belong to t<br \/>he set &#8220;unicode, utf7, utf8, utf32, ascii, bigendianunicode, default, oem&#8221;.<br \/>At line:1 char:32<br \/>+ gps |out-file foo.txt -Encoding&nbsp; &lt;&lt;&lt;&lt; UTF-8<\/font><\/p>\n<p>That is fine for the interactive case but what about the programmatic case &#8211; can you find this info out?&nbsp; The answer is: maybe.&nbsp; <\/p>\n<p>We designed PowerShell (formerly known as Monad) for this scenario. When a cmdlet developer declares their parameters, we provide them a set of VALIDATION attributes that we encourage them to use.&nbsp; At first glance, a developer might say &#8211; the heck with those, it would be just as simple to code this myself.&nbsp; BUT WAIT &#8212; DON&#8217;T DO THAT.&nbsp; <\/p>\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<em><font color=\"#ff0000\">PSTIP: Use the Attributes Luke<\/font><\/em><\/p>\n<p>There are 2 primary benefits of using the attributes instead of coding them yourself <\/p>\n<ol>\n<li>PowerShell engine does the work and will generate the error messages.&nbsp; That might sound trivial but I can guarantee you that if 100 cmdlet developers write their own code, you&#8217;ll get at least 200 error messages for the exact same condition. Using the Attributes ensures a consistent user experience.&nbsp; \n<p>Don&#8217;t care about your user&#8217;s experience?&nbsp; Then there is an economic advantage to using the attributes.&nbsp; Use them and Microsoft will pick up the bill for translating them into all the languages your customers want.&nbsp; (Consistency through economics &#8211; do you see the pattern here?)<\/p>\n<li>The attributes provide a programmable way to discover the capabilities of the cmdlet.&nbsp; This can be used in all sorts of wonderful ways &#8211; e.g. autogenerating GUI front end to the cmdlets.&nbsp; If we know what the parameters are and we also know what the valid values are, we can turn that into a combo-box instead of having the user TYPE the values.<\/li>\n<\/ol>\n<p>If Cmdlet developers don&#8217;t do use the Attributes, you get none of this.&nbsp; <\/p>\n<p>Let&#8217;s explore the CmdletInfo datastructure. This is what is returned when you do a Get-Command (gcm) on a cmdlet.&nbsp;<\/p>\n<p><font face=\"Courier New\" color=\"#000080\" size=\"1\">PS&gt; <strong>gcm out-file |gm param*<br \/><\/strong>&nbsp;&nbsp; TypeName: System.Management.Automation.CmdletInfo<\/font><\/p>\n<p><font face=\"Courier New\" color=\"#000080\" size=\"1\">Name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MemberType Definition<br \/>&#8212;-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8212;&#8212;&#8212;- &#8212;&#8212;&#8212;-<br \/>ParameterSets Property&nbsp;&nbsp; System.Collections.ObjectModel.ReadOnlyCollecti&#8230;<\/font><\/p>\n<p>ParameterSets are the Sets of valid parameters (are we good at naming or what?).&nbsp; For instance, Get-Process (gps) can be provided an -ID parameter or a -NAME parameter.&nbsp; These are 2 ParameterSets for that cmdlet.<\/p>\n<p><font face=\"Courier New\"><font size=\"1\"><font color=\"#000080\">P<\/font><font color=\"#000080\">S&gt; <strong>gps -Name powershell<\/strong><\/font><\/font><\/font><\/p>\n<p><font face=\"Courier New\" color=\"#000080\" size=\"1\">Handles&nbsp; NPM(K)&nbsp;&nbsp;&nbsp; PM(K)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WS(K) VM(M)&nbsp;&nbsp; CPU(s)&nbsp;&nbsp;&nbsp;&nbsp; Id ProcessName<br \/>&#8212;&#8212;-&nbsp; &#8212;&#8212;&nbsp;&nbsp;&nbsp; &#8212;&#8211;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8212;&#8211; &#8212;&#8211;&nbsp;&nbsp; &#8212;&#8212;&nbsp;&nbsp;&nbsp;&nbsp; &#8212; &#8212;&#8212;&#8212;&#8211;<br \/>&nbsp;&nbsp; 1112&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 15&nbsp;&nbsp; 112816&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 19812&nbsp;&nbsp; 250&nbsp;&nbsp; 206.61&nbsp;&nbsp;&nbsp; 936 powershell<\/font><\/p>\n<p><font face=\"Courier New\" color=\"#000080\" size=\"1\">PS&gt; <strong>gps -ID 936<\/strong><\/font><\/p>\n<p><font face=\"Courier New\" color=\"#000080\" size=\"1\">Handles&nbsp; NPM(K)&nbsp;&nbsp;&nbsp; PM(K)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WS(K) VM(M)&nbsp;&nbsp; CPU(s)&nbsp;&nbsp;&nbsp;&nbsp; Id ProcessName<br \/>&#8212;&#8212;-&nbsp; &#8212;&#8212;&nbsp;&nbsp;&nbsp; &#8212;&#8211;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8212;&#8211; &#8212;&#8211;&nbsp;&nbsp; &#8212;&#8212;&nbsp;&nbsp;&nbsp;&nbsp; &#8212; &#8212;&#8212;&#8212;&#8211;<br \/>&nbsp;&nbsp; 1119&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 15&nbsp;&nbsp; 112920&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 19984&nbsp;&nbsp; 250&nbsp;&nbsp; 206.66&nbsp;&nbsp;&nbsp; 936 powershell<br \/><\/font><\/p>\n<p>Out-File has only one parameterSet<\/p>\n<p><font face=\"Courier New\" color=\"#000080\" size=\"1\">PS&gt; <strong>(gcm out-file).Parametersets |fl name<br \/><\/strong>Name : __AllParameterSets<\/font><\/p>\n<p>ParameterSets have a set of Parameters.&nbsp; One of those is the Encoding parameter:<\/p>\n<p><font face=\"Courier New\" color=\"#000080\" size=\"1\">PS&gt; <strong>$p=(gcm out-file).Parametersets[0].parameters |?{$_.name -eq &#8220;Encoding&#8221;}<\/strong><\/font><\/p>\n<p><font face=\"Courier New\" color=\"#000080\" size=\"1\">PS&gt; $p<br \/>Name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : Encoding<br \/>ParameterType&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : System.String<br \/>IsMandatory&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : False<br \/>IsDynamic&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : False<br \/>Position&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : 1<br \/>ValueFromPipeline&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : False<br \/>ValueFromPipelineByPropertyName : False<br \/>ValueFromRemainingArguments&nbsp;&nbsp;&nbsp;&nbsp; : False<br \/>HelpMessage&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; :<br \/>Aliases&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : {}<br \/><strong><font color=\"#ff0000\">Attributes<\/font><\/strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : {System.Management.Automation.ValidateSet<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Attribute, __AllParameterSets, System.Man<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; agement.Automation.ValidateNotNullOrEmpty<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Attribute}<\/font><\/p>\n<p>Notice that this also tells you if the parameter has an alias, is positional, etc.&nbsp; That parameter has a set of Attributes:<\/p>\n<p><font face=\"Courier New\" color=\"#000080\" size=\"1\">PS&gt; <strong>$p.Attributes |ft Typeid<\/strong><\/font><\/p>\n<p><font face=\"Courier New\" color=\"#000080\" size=\"1\">TypeId<br \/>&#8212;&#8212;<br \/>System.Management.Automation.<strong><font color=\"#ff0000\">ValidateSetAttribute<br \/><\/font><\/strong>System.Management.Automation.ParameterAttribute<br \/>System.Management.Automation.ValidateNotNullOrEmptyAttribute<\/font><\/p>\n<p>The ValidateSetAttribute has the list of valid strings for this Parameter:<\/p>\n<p><font face=\"Courier New\" color=\"#000080\" size=\"1\">PS&gt; <strong>($p.Attributes|? {$_.Typeid -match &#8220;ValidateSetAttribute&#8221; }).ValidValues<\/strong><br \/>unicode<br \/>utf7<br \/>utf8<br \/>utf32<br \/>ascii<br \/>bigendianunicode<br \/>default<br \/>oem<\/font><\/p>\n<p>And there you have it.&nbsp; A little chewy yes but I don&#8217;t expect end-users to ever care about this but system programmers and tool vendors will.<\/p>\n<p>Enjoy!<br \/>Jeffrey Snover [MSFT]<br \/>Windows PowerShell Architect<\/p>\n<p>PSMDTAG:FAQ: Is there a programmatic way to get valid string values for a parameter?<br \/>PSMDTAG:PHILOSOPHY: Use Attributes instead of code for validating parameters.<br \/>PSMDTAG:INTERNAL: walk through of the Parameter data for cmdlets<\/p>\n","protected":false},"excerpt":{"rendered":"<p>&lt;WIZARD WARNING&gt;&nbsp; ISVs and Tool vendors may find this important, Advanced users may find this interesting, Casual users may want to skip this. Someone asked me if there was a programmatic way to tell what the legal values for a string parameter to a cmdlet was.&nbsp; The example was OUT-FILE -ENCODING xxx Out current&nbsp;help doesn&#8217;t [&hellip;]<\/p>\n","protected":false},"author":600,"featured_media":13641,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[10,19,11],"class_list":["post-10321","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-powershell","tag-faq","tag-internal","tag-philosophy"],"acf":[],"blog_post_summary":"<p>&lt;WIZARD WARNING&gt;&nbsp; ISVs and Tool vendors may find this important, Advanced users may find this interesting, Casual users may want to skip this. Someone asked me if there was a programmatic way to tell what the legal values for a string parameter to a cmdlet was.&nbsp; The example was OUT-FILE -ENCODING xxx Out current&nbsp;help doesn&#8217;t [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/posts\/10321","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/users\/600"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/comments?post=10321"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/posts\/10321\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/media\/13641"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/media?parent=10321"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/categories?post=10321"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/tags?post=10321"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}