【问题标题】:Nested parameters for Powershell cmdletPowershell cmdlet 的嵌套参数
【发布时间】:2014-12-15 07:28:14
【问题描述】:

新手问题。

如何为 Powershell cmdlet 声明嵌套参数?我想要一个看起来像这样的 cmdlet。

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

我尝试使用ParameterSetName 参数将DefendersMidfielders 下的参数组合在一起。但是当我执行help New-FootballTeam 时,DefendersMidfielders 标记不会出现,我会看到类似这样的内容。

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

谢谢,提前。

【问题讨论】:

  • PowerShell 中的参数集是互斥的(尽管某些参数可以在所有参数集中)。这是你的意图吗?您不能同时指定 -LeftBack 和 -LeftWing?如果不是这样,为什么需要参数 -Defenders 和 -Midfielders?你可以有 -LeftBackDefender、-RightBackDefender、-LeftWingMidfielder 等。
  • 我的意图只是实现一个 cmdlet,就像我上面提到的那样。在这里发帖之前,我正在寻找方法并遇到了 ParameterSets 并在这里写了它,因为我不知道它是否可以成为解决方案。是的。有明显的变通方法,例如使用 -LeftBackDefender 和 -RightBackDefender。但肯定有一种方法可以按照我在问题中提到的方式实现它吗?

标签: c# powershell


【解决方案1】:

PowerShell 不支持您所描述的参数嵌套。 PowerShell 支持多个参数集,允许您指定对特定命令调用有效的不同“集”参数。 ParameterSets(除了内部的 AllParametersSet - 没有分配参数集的参数被放置)是互斥的。通常每个参数集都有一个唯一的参数,PowerShell 使用该参数来选择用于参数解析的特定参数集 - 这是互斥位。如果 PowerShell 无法确定使用哪个参数集,它将发出错误。在某些情况下,您可以通过使用[CmdletBinding(DefaultParameterSet="&lt;defaultParameterSetName&gt;")] 来帮助 PowerShell,告诉 PowerShell 在无法根据提供的参数和参数确定时使用哪个参数集。

【讨论】:

    【解决方案2】:

    有一个简洁的 powershell 功能称为动态参数,您可以使用它来解决这个问题。虽然有点啰嗦:

    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"
            }
        }
    
    }
    

    但是,此解决方案有一些注意事项 - 使用 Get-Help 时不会列出动态参数,而 Intellisense 有时也可以使用它们。但它确实有效,并且由于示例中的参数设置为强制,当设置了后卫/中场开关时,PS 会提示您输入所需的侧翼/后卫。

    【讨论】:

    • 是c#代码吗?这不是我可以在 c# 上重写它的方式吗?
    【解决方案3】:

    像这样定义你的参数:

    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
        )
    
    }
    

    会给你想要的东西:

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

    虽然我不太确定这个示例中的参数集或参数 Defenders 和 Midfielders 的意义。您可以通过参数名称准确地说明您的意思。将所有位置作为参数放在一个集合中会更简单。

    【讨论】:

    • 那行不通,因为 OP 不希望这些参数是互斥的,并且参数集是互斥的。
    • @KeithHill 也许我根据问题的格式误解了 OP 在寻找什么。我想在需要的地方设置两个参数。我不确定您所说的“互斥”是什么意思。当然,当您调用命令时,它必须解析为单个明确的参数集,但参数可以是一个、全部或选择参数集。
    • 是的,但您的定义不允许为单个调用指定后卫和中场。虽然您可以将五个“嵌套”参数放在两个参数集中,但顶级参数集(后卫和中场)仍然是互斥的,因此这两个参数不能出现在同一个调用中。
    猜你喜欢
    • 2020-10-12
    • 1970-01-01
    • 2010-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-07
    • 1970-01-01
    • 2023-04-10
    相关资源
    最近更新 更多