Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Enum parameter for powershell cmdlet

I'm writing a cmdlet (script) on powershell and I wanted to use eunm as one of the parameters. But I don't know where to put enum definition so that it would be visible for cmdlet parameters declaration.

For example, I have a parameters definition of the script like this

[cmdletbinding()]
param(
    [Parameter(Mandatory=$True)]
    [string]$Level
)

and an enum like this

enum LevelEnum { NC = 1; NML = 2; CS = 3 }

I can't replace [string] with [LevelEnum] in the parameter definition because script will fail to locate enum definition. And I can't put definition before cmdletbinding, it's not allowed. I know how to do it if that would've been a function, I know it can be solved using ValidateSet, but I need to have integer values correstonding to enum options.

[ValidateSet('NC','NML','CS')]

But the question is, can I do the same for a cmdlet?


Thanks to everyone. I ended up with a combination of defferent answers.

[cmdletbinding()]
param(
    [Parameter(Mandatory=$True)]
    [ValidateSet('NC','NML','CS')]
    [string]$Level
)
# Convert level from string to enum
enum PatchLevel { NC = 1; NML = 2; CS = 3 }
[PatchLevel]$l = $Level

# Use the numeric value
Write-Host $l.value__
like image 946
Mak Sim Avatar asked Jun 22 '20 09:06

Mak Sim


People also ask

How do I create an enum in PowerShell?

Create an EnumDefine a new enum using Add-Type. Once the enum type has been added to the console environment, it can not be removed or re-defined. Closing and re-opening the console session will remove the enum. In PowerShell 5.0+, the enum keyword makes this even easier.

How do I set parameters in PowerShell?

To create a parameter set, you must specify the ParameterSetName keyword of the Parameter attribute for every parameter in the parameter set. For parameters that belong to multiple parameter sets, add a Parameter attribute for each parameter set.

What is param () in PowerShell?

The PowerShell parameter is a fundamental component of any script. A parameter is a way that developers enable script users to provide input at runtime. If a PowerShell script's behavior needs to change in some way, a parameter provides an opportunity to do so without changing the underlying code.

How do you pass parameters to a function in PowerShell?

You can pass the parameters in the PowerShell function and to catch those parameters, you need to use the arguments. Generally, when you use variables outside the function, you really don't need to pass the argument because the variable is itself a Public and can be accessible inside the function.


3 Answers

Unlike every other part of the PowerShell grammar, type definitions (and using statements) are emitted at parse-time, and you can leverage this by placing the enum definition inside the script or function that depends on it (however counter-intuitive it might seem):

[cmdletbinding()]
param(
    [Parameter(Mandatory=$True)]
    [LevelEnum]$Level
)

begin {
enum LevelEnum { NC = 1; NML = 2; CS = 3 }
}

end {
 # rest of your script goes here
}
like image 60
Mathias R. Jessen Avatar answered Oct 19 '22 15:10

Mathias R. Jessen


I would try something like this:

Below I created a plain PSM1 file with the LevelEnum definition.

enum LevelEnum{
  High
  Medium
  Low
}

Afterwards, I use using module with the path to the PSM1 file.

using module C:\Users\Path\To\Module\testmodule.psm1

function Get-Verb {
    [CmdletBinding()]
    param (
        [LevelEnum]$b
    )
    Write-Host $b
}

I used this microsoft documentation, About_Using and I also run version 7.0.2.

like image 4
Alex_P Avatar answered Oct 19 '22 15:10

Alex_P


If this script needs to accept a custom enum, it means that you will be calling it from some other place, where enum definition already exists. And now you're trying to add the same definition again in a script. It would be good idea to push it out to a module as per @Alex_P suggestion so the definition resides in one place, but the downside is that Import-Module or #Requires won't import it, thus the need for using module clause.

But if you're willing to accept simpler and less secure solution, you could take advantage of the fact that any enum you define is derived from System.Enum. [System.Enum]$Level will accept only and all enums and if it's not LevelEnum the script will break, but still it filters most possible mistakes before the script execution and gives some information about parameter type.

like image 3
AdamL Avatar answered Oct 19 '22 13:10

AdamL