So I originally asked this for a cmdlet written in PowerShell, see: Ambiguous in Powershell Question
The answer for that question works, but only for PowerShell script cmdlets. So here again is the question, but for C# cmdlets ...
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 C# cmdlet shows:
Get-ArgTest [-Width <Object>] [-Height <Object>] [<CommonParameters>]
Get-ArgTest [-Width <Object>] [-HeightReset] [<CommonParameters>]
Get-ArgTest [-Height <Object>] [-WidthReset] [<CommonParameters>]
Get-ArgTest [-WidthReset] [-HeightReset] [<CommonParameters>]
Help for the PS cmdlet shows:
PS C:\> .\get-ArgTestPs.ps1 -?
get-ArgTestPs.ps1 [-Width <int>] [-Height <int>] [<CommonParameters>]
get-ArgTestPs.ps1 [-Width <int>] [-HeightReset] [<CommonParameters>]
get-ArgTestPs.ps1 [-Height <int>] [-WidthReset] [<CommonParameters>]
get-ArgTestPs.ps1 -WidthReset -HeightReset [<CommonParameters>]
See the following code.
Now Get-ArgTest -Width 5
seems to be ambiguous.
Why is this different that cmdlets implemented in PowerShell directly?
Example output:
PS C:\> Get-ArgTest -Width 5 -HeightReset
Begin!
HELLO, Width=5, Height=, WidthReset=False, HeightReset=True
PS C:\> Get-ArgTest -Width 5
Get-ArgTest: Parameter set cannot be resolved using the specified named parameters. One or more parameters issued cannot be used together or an insufficient number of parameters were provided.
PS
The tests:
## Try each combination
# First, just the values
Get-ArgTest # FAIL
Get-ArgTest -Width 2 # FAIL
Get-ArgTest -Height 4 # FAIL
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
Get-ArgTest -WidthReset
Get-ArgTest -HeightReset
The C# code is:
[Cmdlet("Get", "ArgTest")]
[CmdletBinding(DefaultParameterSetName = "A")]
public class ArgTestCmdlet : PSCmdlet
{
[Parameter(ParameterSetName = "A")]
[Parameter(ParameterSetName = "B")]
public object Width;
[Parameter(ParameterSetName = "C")]
[Parameter(ParameterSetName = "A")]
public object Height;
[Parameter(ParameterSetName = "C")]
[Parameter(ParameterSetName = "D", Mandatory = true)]
public SwitchParameter WidthReset;
[Parameter(ParameterSetName = "B")]
[Parameter(ParameterSetName = "D", Mandatory = true)]
public SwitchParameter HeightReset;
// This method gets called once for each cmdlet in the pipeline when the pipeline starts executing
protected override void BeginProcessing()
{
WriteObject("Begin!");
}
// This method will be called for each input received from the pipeline to this cmdlet; if no input is received, this method is not called
protected override void ProcessRecord()
{
}
// This method will be called once at the end of pipeline execution; if no input is received, this method is not called
protected override void EndProcessing()
{
WriteObject($"HELLO, Width={Width}, Height={Height}, WidthReset={WidthReset}, HeightReset={HeightReset}");
}
}
CodePudding user response:
The CmdletBinding
attribute is for declaring cmdlet-like binding behavior on script cmdlets (or "advanced functions" as they're sometimes called).
For a binary cmdlet you need to specify the default parameter set name in the Cmdlet
decorator instead:
[Cmdlet("Get", "ArgTest", DefaultParameterSetName = "A")]
public class ArgTestCmdlet : PSCmdlet
{
// the rest stays the same ...
}