Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Double mutual exclusive parameters with Powershell

Tags:

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:

  • foo -param1_A -param2_A
  • foo -param1_B -param2_A
  • foo -param1_A -param2_B
  • foo -param1_B -param2_B

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.

like image 831
Steve B Avatar asked Nov 12 '13 11:11

Steve B


3 Answers

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
like image 67
Steve B Avatar answered Oct 23 '22 05:10

Steve B


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.

like image 39
ravikanth Avatar answered Oct 23 '22 05:10

ravikanth


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?

like image 1
Chris Avatar answered Oct 23 '22 05:10

Chris