简体   繁体   中英

Nested parameters for Powershell cmdlet

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.

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.

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. 动态参数-仅防御者动态参数=后卫和中场

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM