70

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.

4 Answers 4

122

I would use a ValidateSet parameter attribute instead.

From: about_Functions_Advanced_Parameters

The ValidateSet attribute specifies a set of valid values for a parameter or variable. Windows PowerShell generates an error if a parameter or variable value 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

Output:

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

Sign up to request clarification or add additional context in comments.

4 Comments

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. :-)
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 :)
Keith, you get tab expansion on ValidateSet if you use PowerTab... just sayin. ;)
You do get tab expansion for sets, now (testing in Windows 8.1, in both Powershell 3.0 & 4.0, but not 2.0)
13

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

Comments

10

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 *

5 Comments

But how can I use these examples of enum for command line "param" purposes?
an interesting example, but I think it's not really useful in this case.
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).
For what it's worth, I think it's worth mentioning that using a real enum allows for Get-Help to provide help to script users without making it an opaque runtime minefield. In the example here, Get-Help would show: SYNTAX foo -enum {A | B | C | D}
Tab completion for validate set members seems to work now that we're in the future.
9

Since PowerShell 5 you can actually use/create an Enum natively.

enum OS {
    Windows
    Linux
    iOS
}

This is then also visible as its type.

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     OS                                       System.Enum

Maybe a useful link by 4sysops.

To use it in a function, I would either create a separate .psm1 file and add all the enums you need - see my comment which refers to a similiar question - or you can set this enum at the top of your .psm1 file and use in the same file.

For example, I created the file test.psm1 and added this code:

enum OS {
    Windows
    Linux
    iOS
}

function Get-OS {
    param (
        [Parameter(Mandatory)]
        [OS]$os
    )

    Write-Host -Object "The operating system is $os."
    
}

I import the file Import-Module .\test.psm1 and run it:

PS > Get-OS -os Linux
The operating system is Linux.

2 Comments

How would you use this in a powershell script as OP asked? Because as far as I know you can't put the enum in front of the initial param call.
@IvoMerchiers, here is a SO question regarding the use of enums in Powershell. stackoverflow.com/questions/62511588/…

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.