Using a .NET Enumeration for PowerShell Parameter Validation

I recently ran into an issue where I wanted to use the values from a .NET enumeration as the default values for a parameter. That was easy enough:

1function Test-ConsoleColorValidation {
2    [CmdletBinding()]
3    param (
4        [ValidateNotNullOrEmpty()]
5        [string[]]$Color = [System.Enum]::GetValues([System.ConsoleColor])
6    )
7    $Color
8}

enum-param-validation1a.jpg

Although the previous code met my initial requirements, I decided that I also wanted the user to be able to tab expand the values and to validate the values based on the list of colors found in the enumeration without a requirement of having to hard code the values.

My first thought was to use the ValidateSet parameter validation attribute, but it appears that would require static values to be used for the valid colors. Next, I tried using a dynamic parameter which added too much complexity for what I was trying to accomplish:

 1function Test-ConsoleColorValidation {
 2
 3    [CmdletBinding()]
 4    param ()
 5
 6    DynamicParam {
 7        $Values = [System.Enum]::GetValues([System.ConsoleColor])
 8        $DynParamDictionary = New-Object -TypeName System.Management.Automation.RuntimeDefinedParameterDictionary
 9        $ParamAttributes = New-Object -TypeName System.Management.Automation.ParameterAttribute
10        $AttribColl = New-Object -TypeName System.Collections.ObjectModel.Collection[System.Attribute]
11        $AttribColl.Add($ParamAttributes)
12        $AttribColl.Add((New-Object -TypeName System.Management.Automation.ValidateSetAttribute($Values)))
13        $DynamicParameter = New-Object -TypeName System.Management.Automation.RuntimeDefinedParameter(
14            'Color',
15            [string[]],
16            $AttribColl
17        )
18        $DynParamDictionary.Add('Color', $DynamicParameter)
19        $DynParamDictionary
20    }
21
22    BEGIN {
23        if ($PSBoundParameters -notcontains 'Color') {
24            $PSBoundParameters.Add('Color', $Values)
25        }
26
27        $PSBoundParameters.GetEnumerator() |
28        ForEach-Object {New-Variable -Name $_.Key -Value $_.Value -ErrorAction SilentlyContinue}
29    }
30
31    PROCESS {
32        $Color
33    }
34}

enum-param-validation2a.jpg

I discovered that there's actually an easy way to accomplish this task while eliminating all that unnecessary complexity.

Simply use the class ([System.ConsoleColor] in this example) that describes the .NET enumeration as the parameter data type:

1function Test-ConsoleColorValidation {
2    [CmdletBinding()]
3    param (
4        [ValidateNotNullOrEmpty()]
5        [System.ConsoleColor[]]$Color = [System.Enum]::GetValues([System.ConsoleColor])
6    )
7    $Color
8}

The solution shown in the previous example meets all of my requirements.

It allows all colors in the enumeration to be used as the default value when the Color parameter is not specified without having to hard code the colors:

enum-param-validation1a.jpg

The valid values (colors in this scenario) which are part of the enumeration can be tab expanded and they show up in intellisense:

enum-param-validation2a.jpg

If an invalid color which is not a valid color as far as the enumeration is concerned happens to be specified, a meaningful error message is generated which provides the user of the function with a list of valid values:

enum-param-validation3a.jpg

Reference:

µ