Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PowerShell can't use the matching enum type?

Am I doing something stupid here?

I specify that a function takes a particular enum type as an argument:

PS> add-type -AssemblyName System.ServiceProcess
PS> function test([System.ServiceProcess.ServiceControllerStatus]$x) { Write-host $x $x.gettype() }

The type is most definitely in scope since I can access instances of it (and I imported the assembly manually):

PS> [System.ServiceProcess.ServiceControllerStatus]::Stopped
Stopped

Then when I try to pass the function an instance of said enum, it errors out:

PS> test [System.ServiceProcess.ServiceControllerStatus]::Stopped
test : Cannot process argument transformation on parameter 'x'. Cannot convert value
"[System.ServiceProcess.ServiceControllerStatus]::Stopped" to type "System.ServiceProcess.ServiceControllerStatus".
Error: "Unable to match the identifier name [System.ServiceProcess.ServiceControllerStatus]::Stopped to a valid
enumerator name.  Specify one of the following enumerator names and try again: Stopped, StartPending, StopPending,
Running, ContinuePending, PausePending, Paused"
At line:1 char:6
+ test [System.ServiceProcess.ServiceControllerStatus]::Stopped
+      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidData: (:) [test], ParameterBindingArgumentTransformationException
    + FullyQualifiedErrorId : ParameterArgumentTransformationError,test

It's quite happy coercing a string, though:

PS> test 'Stopped'
Stopped System.ServiceProcess.ServiceControllerStatus

What's going on?

like image 847
jpmc26 Avatar asked Sep 08 '14 20:09

jpmc26


2 Answers

You are running into a small gotcha regarding parsing modes. You can put parens around the argument and it will work:

test ([System.ServiceProcess.ServiceControllerStatus]::Stopped)

Alternatively, conversions from string to enum happen naturally, so you could write:

test Stopped

Here are a couple good links that discuss parsing modes:

  • About Parsing
  • Effective PowerShell Item 10: Understanding PowerShell Parsing Modes
like image 164
Jason Shirk Avatar answered Sep 28 '22 01:09

Jason Shirk


You can pass an enum value as a string but you don't pass the typename as part of the argument e.g. this works just fine:

PS> test Stopped
Stopped System.ServiceProcess.ServiceControllerStatus

That said, when I'm calling .NET methods I prefer to use the fully qualified enum value instead of a string. That's because .NET methods tend to have multiple overloads and those that take strings can confuse PowerShell when to comes to picking the right overload.

like image 40
Keith Hill Avatar answered Sep 27 '22 23:09

Keith Hill