tags:

views:

75

answers:

3

Hi,

I am using switch parameters in my Powershell script in this fashion.

param(
    [switch] $Word,
    [switch] $Excel,
    [switch] $powerpoint,
    [switch] $v2007,
    [switch] $v2010,
    [switch] $x86,
    [switch] $x64,
)

I am trying to figure out any neat way to have it more enum style. As anyone might guess, I would want the user to choose between word, excel and powerpoint. And between x2007 and v2010.

Is there a neat way to get input params enum style?

I am new to powershell. So if this sounds like that I don't know something obvious, then please point me to some link where I can read about it.

Thanks for the help.

A: 

This blog post by the PowerShell team defines how to do this in PowerShell 1.0. In PowerShell 2.0 you can use Add-Type like so:

C:\PS> Add-Type -TypeDefinition @'
>> public enum MyEnum {
>> A,
>> B,
>> C,
>> D
>> }
>> '@
>>

Update: Here's how to use the enum:

C:\PS> function foo([MyEnum]$enum) { $enum }
C:\PS> foo ([MyEnum]::A)
A

You need the parentheses around the argument to parse the argument as a Type. This is required because arguments are treated more or less like strings. Knowing this, you can also pass them enum in a simple string form and powershell will figure it out:

C:\PS> foo A
A
C:\PS> $arg = "B"
C:\PS> foo $arg
B
C:\PS> foo F
error*

error - F is not one of the enumerated values - valid values include A,B,C,D *

Keith Hill
But how can I use these examples of enum for command line "param" purposes?
bits
@Keith an interesting example, but I think it's not really useful in this case.
Jay Bazuzi
Yeah having to use the parens kind of bites. OTOH I like the tab-completion - next best thing to a true static verification of the enum value. ValidateSet is certainly a nice feature to have in the language, just too bad PowerShell doesn't use that info to drive tab-completion. BTW if it were just one set of choices, you could use switches like the OP uses - just put each switch in separate parameter set and pick one to be the default (if none are specified).
Keith Hill
+1  A: 

You can use the ValidateSet attribute:

function My-Func
{
    param (
        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [ValidateSet('Word', 'Excel', 'PowerPoint', 'v2007', 'v2010', 'x86', 'x64')]
        [String]$MyParam
    )

    Write-Host "Performing action for $MyParam"
}

My-Func -MyParam 'Word'
My-Func -MyParam 'v2007'
My-Func -MyParam 'SomeVal'

Output:

Performing action for Word
Performing action for v2007
My-Func : Cannot validate argument on parameter 'MyParam'. The argument "SomeVal" does not belong to the set "Word,Excel,PowerPoint,v2007,v2010,x86,x64" specified by the ValidateSet attribute. Supply an argument that is in the
 set and then try the command again.
At C:\Users\George\Documents\PowerShell V2\ValidateSetTest.ps1:15 char:17
+ My-Func -MyParam <<<<  'SomeVal'
    + CategoryInfo          : InvalidData: (:) [My-Func], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationError,My-Func
George Howarth
+3  A: 

I would use a ValidateSet parameter attribute instead.

From: about_Functions_Advanced_Parameters

"The ValidateSet attribute secifies a set of valid values for the argument of the parameter. The Windows PowerShell runtime generates an error if the parameter argument does not match a value in the set."

Example function:

function test-value
{
    param(
        [Parameter(Position=0)]
        [ValidateSet('word','excel','powerpoint')]
        [System.String]$Application,

        [Parameter(Position=1)]
        [ValidateSet('v2007','v2010')]
        [System.String]$Version
    )


    write-host "Application: $Application"
    write-host "Version: $Version"
}   


PS > test-value -application foo

test-value : Cannot validate argument on parameter 'Application'. The argument "foo" does not belong to the set "word,exce,powerpoint" specified by the ValidateSet attribute. Supply an argument that is in the set and then try the command again.

Shay Levy
This approach forces you into using advanced functions which isn't *always* desirable. You also don't get any form of auto-completion on the enum values. OTOH you don't have to put the enum evaluation within parens e.g. `[MyEnum]::A`. So, a mixed bag I guess. :-)
Keith Hill
Thanks Keith. On the other hand the function needs to implement various parameter checks to find if more than one switch params was specified. BTW, aren't we all using PowerShell v2 :)
Shay Levy
Keith, you get tab expansion on ValidateSet if you use PowerTab... just sayin. ;)
JasonMArcher