2

Newbie Question.

How do I declare nested parameters for a Powershell cmdlet? I want a cmdlet that would look something like this.

New-FootballTeam 
[-Defenders [[-LeftBack] <string>] [[-RightBack] <string>] ]
[-Midfielders [[-LeftWing] <string>] [[-RightWing] <string>] [[-CentreMidfield] <string>] ] 

I tried using the ParameterSetName parameter to club the parameters under Defenders and Midfielders together. But when I do a help New-FootballTeam the Defenders and Midfielders tags don't show up and I see something like this.

New-FootballTeam 
[[-LeftBack] <string>] [[-RightBack] <string>]
[[-LeftWing] <string>] [[-RightWing] <string>] [[-CentreMidfield] <string>] 

Thanks, in advance.

2
  • ParameterSets in PowerShell are mutually exclusive (although some parameters can be in all parametersets). Is that your intent? That you can't specify -LeftBack at the same time as -LeftWing? If that is not the case, why do you need the parameters -Defenders and -Midfielders? You could have -LeftBackDefender, -RightBackDefender, -LeftWingMidfielder, etc. Commented Dec 13, 2014 at 21:17
  • 1
    My intent is just to implement a cmdlet that acts like I mentioned above. Before posting here, I was looking for ways and came across ParameterSets and wrote about it here because I didn't know whether it could be the solution. And yes. There are obvious workarounds like using -LeftBackDefender and -RightBackDefender. But surely there must be a way to implement it the way I have mentioned in the question? Commented Dec 13, 2014 at 21:21

3 Answers 3

3

PowerShell does not support parameter nesting like you have described it. PowerShell supports multiple ParameterSets that allow you specify different "sets" of parameters that are valid for a particular command invocation. ParameterSets (other than the internal AllParametersSet - where parameters that aren't assigned a parameterset are put) are mutually exclusive. Usually each parameterset has a unique parameter that PowerShell uses to select a particular parameter set to use for parameter parsing - that's the mutually exclusive bit. If PowerShell can't determine which parameterset to use it will issue an error. In some cases, you can help PowerShell by using [CmdletBinding(DefaultParameterSet="<defaultParameterSetName>")] to tell PowerShell which parameterset to use when it can't figure it out based on the supplied parameters and arguments.

Sign up to request clarification or add additional context in comments.

Comments

2

There is a neat powershell feature called Dynamic Parameters which you can use to solve this problem. It's a bit long-winded though:

Function New-FootballTeam {
    [CmdletBinding()]
    Param(
        [Switch]$Defenders,
        [Switch]$Midfielders
    )

    DynamicParam {
        $dynamicParameters = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary
        $toAdd = @()

        if ($Defenders) {
            $toAdd += @('LeftBack', 'RightBack')
        }

        if ($Midfielders) {
            $toAdd += @('LeftWing', 'RightWing')
        }

        $toAdd | % {
            $attr = New-Object System.Management.Automation.ParameterAttribute
            $attr.ParameterSetName = "__AllParameterSets"
            $attr.Mandatory = $True

            $attributes = New-Object System.Collections.ObjectModel.Collection[System.Attribute]
            $attributes.Add($attr)

            $param = New-Object System.Management.Automation.RuntimeDefinedParameter(
                $_,
                'string',
                $attributes
            )

            $dynamicParameters.Add($_, $param)
        }

        return $dynamicParameters
    }

    Begin {
        $LeftBack  = $PSBoundParameters.LeftBack
        $RightBack = $PSBoundParameters.RightBack
        $LeftWing  = $PSBoundParameters.LeftWing
        $RightWing = $PSBoundParameters.RightWing
    }

    End {
        if ($Defenders) {
            Write-Host "LeftBack : $LeftBack"
            Write-Host "RightBack: $RightBack"
        }
        if ($Midfielders) {
            Write-Host "LeftWing : $LeftWing"
            Write-Host "RightWing: $RightWing"
        }
    }

}

However, there are a few caveats with this solution - dynamic parameters are not listed when you use Get-Help, and Intellisense can sometimes play up with them too. But it does work, and as the parameters in the example are set to Mandatory, when the Defenders/Midfielders switches are set, PS will prompt you to enter the required Wings/Backs. Dynamic parameters - defenders only Dynamic parameters = defenders and midfielders

1 Comment

is it c# code ? it it's not how i can rewrite it on c# ?
0

Defining your parameter like so:

function New-FootballTeam {

    param(
    [Parameter(Mandatory = $true, ParameterSetName = "Defenders")]
    [switch]$Defenders,
    [Parameter(ParameterSetName = "Defenders", Position = 0)]
    [string]$LeftBack,
    [Parameter(ParameterSetName = "Defenders", Position = 1)]
    [string]$RightBack,
    [Parameter(Mandatory = $true, ParameterSetName = "Midfielders")]
    [switch]$Midfielders,
    [Parameter(ParameterSetName = "Midfielders", Position = 0)]
    [string]$LeftWing,
    [Parameter(ParameterSetName = "Midfielders", Position = 1)]
    [string]$RightWing,
    [Parameter(ParameterSetName = "Midfielders", Position = 2)]
    [string]$CentreMidfield
    )

}

will give you something like what you want:

NAME  
    New-FootballTeam

SYNTAX
    New-FootballTeam [[-LeftBack] <string>] [[-RightBack] <string>] -Defenders  [<CommonParameters>]

    New-FootballTeam [[-LeftWing] <string>] [[-RightWing] <string>] [[-CentreMidfield] <string>] -Midfielders  [<CommonParameters>]

Although I'm not quite sure of the point of the parameter sets or the parameters Defenders and Midfielders in this example. You can tell exactly what you mean by the parameter names. It would be simpler to just have all the positions as parameters in a single set.

3 Comments

That won't work because the OP doesn't want these parameters to be mutually exclusive and parameter sets are mutually exclusive.
@KeithHill maybe I misunderstood what the OP was looking for based on the formatting of the question. I thought two parameter set where desired. I'm not sure what you mean by "mutually exclusive". Certainly, when you invoke a command it has to resolve to a single unambiguous parameter set, but a parameter can be in one, all, or select parameter sets.
Yes but your definition would not allow Defenders and Midfields to be specified for a single invocation. And while you could put the five "nested" parameters in both parametersets, the top level parametersets (Defenders and Midfielders) are still mutually exclusive so those two parameter cannot appear in the same invocation.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.