none
How can I address an enumeration type defined in a module? RRS feed

  • Question

  • In one of our PowerShell modules we have defined an enumeration type:

    myModule.psm1

    [Flags()]
    enum MyEnum {
      Value1 = 1
      Value2 = 2
      Value3 = 4
    }
    
    Function Have-Some
    (
      [Parameter(Mandatory = $true, Position = 0)]
      [MyEnum]
      $enumValue
    ) {
    }

    Now, from a script I'd like to address this type to call the Have-Some function.

    Though, none of the below methods seems to work:

    Have-Some Value1,Value2
    Have-Some "Value1,Value2"
    Have-Some [MyEnum]Value1,Value2
    Have-Some [MyEnum]"Value1,Value2"
    Have-Some [MyEnum]Value1 + [MyEnum]Value2
    Have-Some [MyEnum]Value1 -bor [MyEnum]Value2

    I always get the same (or similar) error:

    Cannot process argument transformation on parameter 'enumValue'. Cannot convert value "[MyEnum]::Value1" to type "MyEnum". Error: "Unable to match the identifier name [MyEnum]::Value1 to a valid enumerator name. Specify one of the following enumerator names and try again: Value1, Value2, Value3"

    What's the correct way to call the Have-Some function with two or more MyEnum flags?

    Tuesday, September 17, 2019 12:44 PM

All replies

  • In one of our PowerShell modules we have defined an enumeration type:

    myModule.psm1

    [Flags()]
    enum MyEnum {
      Value1 = 1
      Value2 = 2
      Value3 = 4
    }
    
    Function Have-Some
    (
      [Parameter(Mandatory = $true, Position = 0)]
      [MyEnum]
      $enumValue
    ) {
    }

    Now, from a script I'd like to address this type to call the Have-Some function.

    Though, none of the below methods seems to work:

    Have-Some Value1,Value2
    Have-Some "Value1,Value2"
    Have-Some [MyEnum]Value1,Value2
    Have-Some [MyEnum]"Value1,Value2"
    Have-Some [MyEnum]Value1 + [MyEnum]Value2
    Have-Some [MyEnum]Value1 -bor [MyEnum]Value2

    I always get the same (or similar) error:

    Cannot process argument transformation on parameter 'enumValue'. Cannot convert value "[MyEnum]::Value1" to type "MyEnum". Error: "Unable to match the identifier name [MyEnum]::Value1 to a valid enumerator name. Specify one of the following enumerator names and try again: Value1, Value2, Value3"

    What's the correct way to call the Have-Some function with two or more MyEnum flags?

    • Edited by BetterToday Tuesday, September 17, 2019 12:43 PM
    • Merged by jrv Tuesday, September 17, 2019 6:39 PM DUPLICAT
    Tuesday, September 17, 2019 12:41 PM
  • An enum can only directly cast one key.  For casting multiple keys as a string you would need to create a special type using C# or VB,Net.


    \_(ツ)_/

    Tuesday, September 17, 2019 6:34 PM
  • The doc is not for an enum. The doc is about a "Flags" structure. Please read it carefully. 

    The "enum" keyword" is a PowerShell construct. The [flags} type is part of the Net Framework.

    When we specify  "[Flags()] enum" we are specifying a flags type of structure that supports what you are trying to do.  "enum" does not.


    \_(ツ)_/

    Wednesday, September 18, 2019 8:50 AM
  • I'm not sure I understand what you're trying to say. The doc reads: "Enumerations can be defined as a collection of bit flags. Where, at any given point the enumeration represents one or more of those flags turned on."

    From my perspective, that's absolutely the definition of an enum. It resembles the .NET enum functionality, but it's native PowerShell, according to the docs.

    And, that's exactly my above code.

    So, how would a structure like this be initialized in PowerShell, so it can be used as an argument in a function call?

    Wednesday, September 18, 2019 11:41 AM
  • Yes but to get a flags enum you must attribute the enum. That tells PowerShell that the enum is not a simple enum but is a flags type of enum.

    The doc makes this very clear. A "flags" enum works completely differently from a regular enum because it represents a bitfield.  Because of this we can specify multiple bits to be set in one string.  A regular enum just decodes a single string and is just s simple translator mechanism to conbert strings into numbers.  A flags enum sets bits in an integer.  It does not represent number assignments.

    The same is true in all Net languages.  The type is part of the net framework and the attribute tells the code that the enum is special and is a bit field and not just a plain integer.

    Remember that bit fields are numbered from right to left and the values are the value of the bit when set. 1,2,4,8,16 …

    PS > [flags()] enum BitField { bit0 = 1 bit1 = 2 bit2 = 4 bit3 = 8 bit4 = 16 bit1And3 = 10 All = 0x1F } PS > [bitfield]'bit1,bit3,bit4' bit1And3, bit4 PS > $b = [bitfield]'bit1' PS > $b bit1 PS > $b += 'bit2' PS > $b bit1, bit2

    PS >$b = [bitfield]'bit1,bit3' PS > [int]$b 10

    PS C:\scripts> $b = [bitfield]'All'
    PS C:\scripts> $b
    All
    PS C:\scripts> [int]$b
    31



    \_(ツ)_/




    • Edited by jrv Wednesday, September 18, 2019 12:02 PM
    Wednesday, September 18, 2019 11:59 AM
  • Did you read my original posting carefully? That's what I actually did.

    Yet, I don#t seem to be able to initialize my above enum when it's stored in a module.

    Can you reproduce my issue?

    Thursday, September 19, 2019 8:56 AM
  • That is because it is private to the module. You need to make it public.

    By the way - this was the question you asked in your first post:

    What's the correct way to call the Have-Some function with two or more MyEnum flags?


    \_(ツ)_/

    Thursday, September 19, 2019 9:12 AM
  • Also to use an enum with multiple values we would do this:

    [myenum]'value1,value2'

    To correctly use this in a function:

    Function Have-Some{
    	Param(
    		[Parameter(Mandatory = $true, Position = 0)]
    		[MyEnum]$enumValue
    	)
    	$enumValue
    }
    
    Have-Some 'value1,value2'


    \_(ツ)_/

    Thursday, September 19, 2019 9:18 AM
  • You can also do this with an enum type of parameter and it will autocomplete as expected

    Have-Some -enumValue Value1,Value2


    \_(ツ)_/

    Thursday, September 19, 2019 9:20 AM
  • Here is a quick example of using this in a module.

    $sb = {
    	[Flags()] enum MyEnum {
    		Value1 = 1
    		Value2 = 2
    		Value3 = 4
    	}
    
    	Function Have-Some{
    		Param(
    			[Parameter(Mandatory = $true, Position = 0)]
    			[MyEnum]$enumValue
    		)
    		$enumValue
    	}
    }
    New-Module -ScriptBlock $sb -name MyModule | Import-Module
    Have-Some -enumValue value1,value2

    We can also use it in reverse:

    PS >Have-Some 6
    Value2, Value3


    \_(ツ)_/



    • Edited by jrv Thursday, September 19, 2019 9:32 AM
    Thursday, September 19, 2019 9:30 AM
  • Now the final part of my best guess as to what you are tryig to ask.

    In the module manifest there is an entry "ScriptsToProcess".  It will execute a PS1 script as if it were dot sourced.  Any variables or custom types or objects that you want available should be put in a PS1 file and referenced here.  I call my file "globals.ps1"

    This is the lien:

    # Script files (.ps1) that are run in the caller's environment prior to importing this module.
    ScriptsToProcess = @('globals.ps1')
    Place the "enum" or any "class" or variables that you want available globally in this list and it will be available globally in a PowerShell session.


    \_(ツ)_/

    Thursday, September 19, 2019 10:47 AM
  • That is because it is private to the module. You need to make it public.

    That's intriguing ... How would I make the enum public? What am I missing?

    Currently, I need to have everything in the module file to be portable. I need a call in a script file, though, for Visual Studio Code to be able to debug the function. So that's a constraint.

    
    |-- psm1 file --------------------------|
    | enum definition                               |
    | function definition                            |
    |---------------------------------------|
    
    |-- ps1 file ---------------------------|
    | function call                                     |
    |---------------------------------------|
    


    • Edited by BetterToday Friday, September 20, 2019 12:50 AM
    Friday, September 20, 2019 12:50 AM
  • Look at my previous 2 posts.

    \_(ツ)_/

    Friday, September 20, 2019 12:52 AM