jpmc26
jpmc26

Reputation: 29876

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?

Upvotes: 8

Views: 7445

Answers (4)

Jason Shirk
Jason Shirk

Reputation: 8019

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:

Upvotes: 14

Aaron Jensen
Aaron Jensen

Reputation: 26749

You're not specifying the $x parameter correctly. It needs to be wrapped in a param() expression.

function test
{
    param(
        [ServiceProcess.ServiceControllerStatus]
        $x
    ) 
    Write-host $x $x.gettype() 
}

Plus you can omit the System. portion of any type name.

Upvotes: -1

Keith Hill
Keith Hill

Reputation: 201652

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.

Upvotes: 2

jpmc26
jpmc26

Reputation: 29876

Apparently, PowerShell thinks I am sending it a string, rather than an enum object. You get the same error message if you quote the fully qualified name:

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

Putting the enum in parentheses to force PowerShell to evaluate it first does the trick:

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

Upvotes: 0

Related Questions