Steve B
Steve B

Reputation: 37710

Double mutual exclusive parameters with Powershell

I'm writing a custom PowerShell function that have multiple possible parameters.

function foo {
    param(
        [Parameter(Mandatory=$true)]
        [string]$param1_A,
        [Parameter(Mandatory=$true)]
        [int]$param1_B,

        [Parameter(Mandatory=$true)]
        [string]$param2_A,
        [Parameter(Mandatory=$true)]
        [int]$param2_B
    )

}

I have basically two sets of mutual exclusive parameters. I can specify either $param1_A or $param1_B, but not both. I also can specify either $param2_A or $param2_B, but not both too.

To sum up, here is a table of possibles calls:

In all cases, at least one of the parameter is mandatory.

How can I declare my parameters to enforce this requirement?

I've tried to use different parameter sets, but I didn't succeed, because I did not find a way to describe the concept of at least one parameter.

If it can help, I have utility functions that can convert $param1_A to $param1_B and $param2_A to $param2_B.

Upvotes: 5

Views: 3456

Answers (4)

ravikanth
ravikanth

Reputation: 25820

You need parametersets

Here is an example from the technet page:

Param
          (
            [parameter(Mandatory=$true,
                      ParameterSetName="Computer")]
            [String[]]
            $ComputerName,

            [parameter(Mandatory=$true,
                      ParameterSetName="User")]
            [String[]]
            $UserName

            [parameter(Mandatory=$false, ParameterSetName="Computer")]
            [parameter(Mandatory=$true, ParameterSetName="User")]
            [Switch]
            $Summary
          )

In your example, you need four parameter sets and you can assign one of them as the default paramter set.

Upvotes: 3

mmseng
mmseng

Reputation: 850

Steve B's answer was what I was looking for, however it was confusing to try to implement, because of the abstract nature of the code example (param1/2 A/B/C/D). Once I sort of grok'd the concept, giving the variables and parameter sets meaningful names really helped me understand what's going on. So I thought I'd share a more concrete example in case it helps others.

Say you want to order a meal. You can choose Pepsi or Coke for the drink (mutually exclusive choice #1). You can choose a burger w/ fries or a salad for the main dish (mutually exclusive choice #2). For the purposes of this, I'll say the given values will just be the integer size of the food item, but that's irrelevant.

param (
    [Parameter(Position=0,Mandatory=$true,ParameterSetName="Pepsi-BurgerFries")]
    [Parameter(Position=0,Mandatory=$true,ParameterSetName="Pepsi-Salad")]
    [int]$Pepsi,

    [Parameter(Position=0,Mandatory=$true,ParameterSetName="Coke-BurgerFries")]
    [Parameter(Position=0,Mandatory=$true,ParameterSetName="Coke-Salad")]
    [int]$Coke,

    [Parameter(Mandatory=$true,ParameterSetName="Pepsi-BurgerFries")]
    [Parameter(Mandatory=$true,ParameterSetName="Coke-BurgerFries")]
    [int]$Burger,

    [Parameter(Mandatory=$true,ParameterSetName="Pepsi-BurgerFries")]
    [Parameter(Mandatory=$true,ParameterSetName="Coke-BurgerFries")]
    [int]$Fries,

    [Parameter(Mandatory=$true,ParameterSetName="Pepsi-Salad")]
    [Parameter(Mandatory=$true,ParameterSetName="Coke-Salad")]
    [int]$Salad
)

Upvotes: 0

Chris
Chris

Reputation: 11

The post marked as solution is nice and relatively handy for the case you have 2 sets of mutual parameters. In that case you have 2x2=4 parameter Sets. Lets asume you have not 2 but 3 sets of 2 parameters. This results in 2x2x2=8 necessary ParameterSets. That means at least 8 lines for every parameter -> 6x8=48 lines only for a declarative part. Not mentioning the concentration to correctly assign the correct ParameterSets to each parameter. Doesn't exist a better way for a simple syntax like this:

(-a|-b) (-c|-d) (-e|-f)...

Edit: Here a clarification of what i would like to realise:

Param(
    [string]$a1="some value to create a2",

    [PsObject]$a2,

    [string]$b1="some value to create a2",

    [PsObject]$b2,

    [string]$c1="some value to create a2",

    [PsObject]$c2,
)

For my function it should be necessary to provide (a1 or a2) and (b1 or b2) and (c1 or c2). Because a2, b2 and c3 can be created through the default values of a1, b1 and c1 all parameters with n2 (where n = a or b or c) should pe optional (Mandatory = false). Because i have default Values for n1 (where n = a or b or c), they arent mandatory, too.

To come back to my original question: I could build ParameterSets for every permutation of parameter entry possibilities. That would result in a lot of work as much different parameters i have.

Example:

Param(
    [Parameter(Position=0)]
    [Parameter(ParameterSetName="a1b1c1", Mandatory=$false)]
    [Parameter(ParameterSetName="a1b1c2", Mandatory=$false)]
    [Parameter(ParameterSetName="a1b2c1", Mandatory=$false)]
    [Parameter(ParameterSetName="a1b2c2", Mandatory=$false)]
    [string]$a1="some value to create a2",

    [Parameter(Position=0)]
    [Parameter(ParameterSetName="a2b1c1", Mandatory=$false)]
    [Parameter(ParameterSetName="a2b1c2", Mandatory=$false)]
    [Parameter(ParameterSetName="a2b2c1", Mandatory=$false)]
    [Parameter(ParameterSetName="a2b2c2", Mandatory=$false)]
    [PsObject]$a2,

    [Parameter(Position=1)]
    [Parameter(ParameterSetName="a1b1c1", Mandatory=$false)]
    [Parameter(ParameterSetName="a1b1c2", Mandatory=$false)]
    [Parameter(ParameterSetName="a2b1c1", Mandatory=$false)]
    [Parameter(ParameterSetName="a2b1c2", Mandatory=$false)]
    [string]$b1="some value to create a2",

    [Parameter(Position=1)]
    [Parameter(ParameterSetName="a1b2c1", Mandatory=$false)]
    [Parameter(ParameterSetName="a1b2c2", Mandatory=$false)]
    [Parameter(ParameterSetName="a2b2c1", Mandatory=$false)]
    [Parameter(ParameterSetName="a2b2c2", Mandatory=$false)]
    [PsObject]$b2,

    [Parameter(Position=2)]
    [Parameter(ParameterSetName="a1b1c1", Mandatory=$false)]
    [Parameter(ParameterSetName="a1b2c1", Mandatory=$false)]
    [Parameter(ParameterSetName="a2b1c1", Mandatory=$false)]
    [Parameter(ParameterSetName="a2b2c1", Mandatory=$false)]
    [string]$c1="some value to create a2",

    [Parameter(Position=2)]
    [Parameter(ParameterSetName="a1b1c2", Mandatory=$false)]
    [Parameter(ParameterSetName="a1b2c2", Mandatory=$false)]
    [Parameter(ParameterSetName="a2b1c2", Mandatory=$false)]
    [Parameter(ParameterSetName="a2b2c2", Mandatory=$false)]
    [PsObject]$c2,
)

You can easyly see how complex and long it gets compared with first Post. However it even doesn't work because of all the Mandatory=false Parameters.

Any suggestions to achive my goal?

Upvotes: 1

Steve B
Steve B

Reputation: 37710

Ok, I manage to use the parameter sets. What I didn't understand before, is that I can declare multiple [Parameter] attributes on the same parameter. So as suggested mjolinor, I can actually use parameter sets.

Here is the updated code of my function:

function foo {
    param(
        [Parameter(Mandatory=$true, ParameterSetName='A')]
        [Parameter(Mandatory=$true, ParameterSetName='C')]
        [string]$param1_A,
        [Parameter(Mandatory=$true, ParameterSetName='B')]
        [Parameter(Mandatory=$true, ParameterSetName='D')]
        [int]$param1_B,

        [Parameter(Mandatory=$true, ParameterSetName='A')]
        [Parameter(Mandatory=$true, ParameterSetName='B')]
        [string]$param2_A,
        [Parameter(Mandatory=$true, ParameterSetName='C')]
        [Parameter(Mandatory=$true, ParameterSetName='D')]
        [int]$param2_B
    )

     $PSCmdlet.ParameterSetName
}

Foo -param1_A 1 -param2_A "1"
Foo -param1_B 1 -param2_A "1"
Foo -param1_A 1 -param2_B "1"
Foo -param1_B 1 -param2_B "1"

Will outputs:

A
B
C
D

Upvotes: 9

Related Questions