alx9r
alx9r

Reputation: 4229

Why does parameter binding succeed with no arguments when there is one parameter set but fails with two?

I have two functions. The first has one parameter set, the second has two parameter sets as follows:

function OneSet{
    [CmdletBinding()]
    param ( $NoSet,
            [parameter(ParameterSetName = 'A')]$A )
    process { $PSCmdlet.ParameterSetName }
}

function TwoSets{
    [CmdletBinding()]
    param ( $NoSet,
            [parameter(ParameterSetName = 'A',Mandatory = $true)]$A,
            [parameter(ParameterSetName = 'B',Mandatory = $true)]$B  )
    process { $PSCmdlet.ParameterSetName }
}

Invoking the first one without arguments results in '__AllParameterSets' binding:

C:\> OneSet
__AllParameterSets

Invoking the second one without arguments throws an exception:

C:\> TwoSets
TwoSets : Parameter set cannot be resolved using the specified named parameters.
+ TwoSets
+ ~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [TwoSets], ParameterBindingException
    + FullyQualifiedErrorId : AmbiguousParameterSet,TwoSets

I don't see why the second case is any more ambiguous than the first. Why doesn't PowerShell bind to TwoSets using the "__AllParameterSets" parameter set?

Is there a (terse) way to have multiple parameter sets and still be able to call the function with no arguments?

Upvotes: 1

Views: 335

Answers (2)

alx9r
alx9r

Reputation: 4229

Edit: I think None could be substituted for __AllParameterSets to achieve the goal of "creating a parameter set with no mandatory parameters at all". For more details see PowerShell/PowerShell#11237, #12619, and #11143


I don't see why the second case is any more ambiguous than the first. Why doesn't PowerShell bind to TwoSets using the "__AllParameterSets" parameter set?

PowerShell seems to use the __AllParameterSets parameter set as a default when there is only one user-named parameter set. On the other hand, when there is more than one user-named parameter set, PowerShell does not seem to consider any parameter set to be a default unless you specify it.

Is there a (terse) way to have multiple parameter sets and still be able to call the function with no arguments?

You can tell PowerShell to use __AllParameterSets as the default as follows:

function TwoSets{
    [CmdletBinding(DefaultParameterSetName = '__AllParameterSets')]
    param ( $NoSet,
            [parameter(ParameterSetName = 'A', Mandatory = $true)]$A,
            [parameter(ParameterSetName = 'B', Mandatory = $true)]$B  )
    process { $PSCmdlet.ParameterSetName }
}

Then invoking with no parameters, -A, or -B yields causes binding to the each of the three parameter sets as follows:

PS C:\> TwoSets
__AllParameterSets

PS C:\> TwoSets -A 'a'
A

PS C:\> TwoSets -B 'b'
B

Upvotes: 0

Mike Shepard
Mike Shepard

Reputation: 18156

It's because PowerShell can't figure out which parameter set you're trying to use. You can tell it what to default to in the CmdletBinding attribute.

function TwoSets{
    [CmdletBinding(DefaultParameterSetName='A')]
    param ( $NoSet,
            [parameter(ParameterSetName = 'A')]$A,
            [parameter(ParameterSetName = 'B')]$B  )
    process { $PSCmdlet.ParameterSetName }
}

Upvotes: 2

Related Questions