Automating the world one-liner at a time…
<WIZARD WARNING> 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. The example was OUT-FILE -ENCODING xxx
Out current help doesn't tell you this information (and it wouldn't be a great programmatic experience even if it did) and neither does Get-Command:
PS> get-command out-file |fl DefinitionDefinition : Out-File [-FilePath] <String> [[-Encoding] <String>] [-Append] [-Force] [-NoClobber] [-Width <Int32>] [-InputObject <PSObjec t>] [-Verbose] [-Debug] [-ErrorAction <ActionPreference>] [-Er rorVariable <String>] [-OutVariable <String>] [-OutBuffer <Int 32>] [-WhatIf] [-Confirm]
It tells me that it takes a string but not what the values are. When you try to assign an incorrect value, you'll be told what the correct values are:
PS> gps |out-file foo.txt -Encoding UTF-8Out-File : Cannot validate argument "UTF-8" because it does not belong to the set "unicode, utf7, utf8, utf32, ascii, bigendianunicode, default, oem".At line:1 char:32+ gps |out-file foo.txt -Encoding <<<< UTF-8
That is fine for the interactive case but what about the programmatic case - can you find this info out? The answer is: maybe.
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. At first glance, a developer might say - the heck with those, it would be just as simple to code this myself. BUT WAIT -- DON'T DO THAT.
PSTIP: Use the Attributes Luke
There are 2 primary benefits of using the attributes instead of coding them yourself
If Cmdlet developers don't do use the Attributes, you get none of this.
Let's explore the CmdletInfo datastructure. This is what is returned when you do a Get-Command (gcm) on a cmdlet.
PS> gcm out-file |gm param* TypeName: System.Management.Automation.CmdletInfo
Name MemberType Definition---- ---------- ----------ParameterSets Property System.Collections.ObjectModel.ReadOnlyCollecti...
ParameterSets are the Sets of valid parameters (are we good at naming or what?). For instance, Get-Process (gps) can be provided an -ID parameter or a -NAME parameter. These are 2 ParameterSets for that cmdlet.
PS> gps -Name powershell
Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName------- ------ ----- ----- ----- ------ -- ----------- 1112 15 112816 19812 250 206.61 936 powershell
PS> gps -ID 936
Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName------- ------ ----- ----- ----- ------ -- ----------- 1119 15 112920 19984 250 206.66 936 powershell
Out-File has only one parameterSet
PS> (gcm out-file).Parametersets |fl nameName : __AllParameterSets
ParameterSets have a set of Parameters. One of those is the Encoding parameter:
PS> $p=(gcm out-file).Parametersets[0].parameters |?{$_.name -eq "Encoding"}
PS> $pName : EncodingParameterType : System.StringIsMandatory : FalseIsDynamic : FalsePosition : 1ValueFromPipeline : FalseValueFromPipelineByPropertyName : FalseValueFromRemainingArguments : FalseHelpMessage :Aliases : {}Attributes : {System.Management.Automation.ValidateSet Attribute, __AllParameterSets, System.Man agement.Automation.ValidateNotNullOrEmpty Attribute}
Notice that this also tells you if the parameter has an alias, is positional, etc. That parameter has a set of Attributes:
PS> $p.Attributes |ft Typeid
TypeId------System.Management.Automation.ValidateSetAttributeSystem.Management.Automation.ParameterAttributeSystem.Management.Automation.ValidateNotNullOrEmptyAttribute
The ValidateSetAttribute has the list of valid strings for this Parameter:
PS> ($p.Attributes|? {$_.Typeid -match "ValidateSetAttribute" }).ValidValuesunicodeutf7utf8utf32asciibigendianunicodedefaultoem
And there you have it. A little chewy yes but I don't expect end-users to ever care about this but system programmers and tool vendors will.
Enjoy!Jeffrey Snover [MSFT]Windows PowerShell Architect
PSMDTAG:FAQ: Is there a programmatic way to get valid string values for a parameter?PSMDTAG:PHILOSOPHY: Use Attributes instead of code for validating parameters.PSMDTAG:INTERNAL: walk through of the Parameter data for cmdlets
It's great to have this info available for someone like me who is writing a book about cmdlets which are in development and the docs aren't even done yet. :)
I am trying to use this to retrieve all the valid values for the -role parameter for the get-help command. I am just using this as an example. Should your code work for this because i cannot get it to. I get as far as the penultimate cmd and the final one returns a blank line.
Thank you
PS I know i can use values like *mailbox* and *um* but i wud like to see how to find these out for myself without having to rely on generous bloggers with inside knowledge :-)