Home > Blockchain >  Sets of mutually exclusive parameters in PowerShell: Why is this ambiguous?
Sets of mutually exclusive parameters in PowerShell: Why is this ambiguous?

Time:03-16

I've been trying to get multiple sets of mutual exclusions to work. I want "Width" mutually exclusive to "WidthReset" and "Height" to be mutually exclusive with "HeightReset".

Help for the cmdlet shows:

    Get-ArgTest [-Width <int>] [-Height <int>]  [<CommonParameters>]
    Get-ArgTest [-Width <int>] [-HeightReset]  [<CommonParameters>]
    Get-ArgTest [-Height <int>] [-WidthReset]  [<CommonParameters>]
    Get-ArgTest [-WidthReset] [-HeightReset]  [<CommonParameters>]

See the following code.

Everything works, but Get-ArgTest -WidthReset seems to be ambiguous.

Why is this one case is ambiguous? Other, symmetrical cases are not flagged as ambiguous.

How can I resolve the ambiguity?

Changing the DefaultParameterSetName to B or C changes which case is ambiguous.

That indicates to me that it should work.

##########################################
# This cmdlet *should* accept
# [-Width | -WidthReset] [-Height | -HeightReset]
##########################################
function Get-ArgTest
{
  [CmdletBinding(DefaultParameterSetName = 'A')]
    param(
            [Parameter(ParameterSetName='A')]
            [Parameter(ParameterSetName='B')]
            [int] $Width,

            [Parameter(ParameterSetName='C')]
            [Parameter(ParameterSetName='A')]
            [int] $Height,

            [Parameter(ParameterSetName='C')]
            [Parameter(ParameterSetName='D')]
            [switch] $WidthReset,

            [Parameter(ParameterSetName='B')]
            [Parameter(ParameterSetName='D')]
            [switch] $HeightReset
    )

    Write-Output "HELLO, Width=$Width, Height=$Height, WidthReset=$WidthReset, HeightReset=$HeightReset"
}

##########################################
# Tests
##########################################
# First, display HELP
Get-ArgTest -?

####
## Try each combination
# First, just the values
Get-ArgTest 
Get-ArgTest -Width 2
Get-ArgTest          -Height 4
Get-ArgTest -Width 2 -Height 4

# Values and the opposite reset
Get-ArgTest -Width 2                         -HeightReset
Get-ArgTest          -Height 4   -WidthReset

# The Resets
Get-ArgTest                      -WidthReset -HeightReset
Get-ArgTest                      -WidthReset -HeightReset:$False
Get-ArgTest                      -WidthReset:$False -HeightReset:$True

# I cannot get the following cases to work :-(
Get-ArgTest                      -WidthReset
Get-ArgTest                                  -HeightReset

CodePudding user response:

To avoid the ambiguity, make -WidthReset and -HeightReset mandatory in your D parameter set:

function Get-ArgTest
{
  [CmdletBinding(DefaultParameterSetName = 'A')]
    param(
            [Parameter(ParameterSetName='A')]
            [Parameter(ParameterSetName='B')]
            [int] $Width,

            [Parameter(ParameterSetName='C')]
            [Parameter(ParameterSetName='A')]
            [int] $Height,

            [Parameter(ParameterSetName='C')]
            [Parameter(ParameterSetName='D', Mandatory)]
            [switch] $WidthReset,

            [Parameter(ParameterSetName='B')]
            [Parameter(ParameterSetName='D', Mandatory)]
            [switch] $HeightReset
    )

    Write-Output "HELLO, Width=$Width, Height=$Height, WidthReset=$WidthReset, HeightReset=$HeightReset"
}

This results in the following syntax diagram (Get-Command -Syntax Get-ArgTest):

Get-ArgTest [-Width <int>] [-Height <int>] [<CommonParameters>]

Get-ArgTest [-Width <int>] [-HeightReset] [<CommonParameters>]

Get-ArgTest [-Height <int>] [-WidthReset] [<CommonParameters>]

Get-ArgTest -WidthReset -HeightReset [<CommonParameters>]

As a result:

  • If both -WidthReset and -HeightReset are present, parameter set D is unambiguously implied.

  • If either -WidthReset or -HeightReset is present, parameter set C or B is unambiguously implied.


As for what you tried:

With your original function definition, the following calls are ambiguous:

Get-ArgTest                      -WidthReset
Get-ArgTest                                  -HeightReset

because the former matches both parameter set C and D,
and the latter both B and D,
and none of them is the default parameter set (which would act as the tie-breaker).

  • Related