如何在 Powershell 中指定静态和动态位置参数?

How do you specify both static and dynamic positional parameters in Powershell?

编辑

根据 The Mad Technician 的建议,我已在 PowerShell UserVoice 网站上提交了一个错误报告:https://windowsserver.uservoice.com/forums/301869-powershell/suggestions/20034763-dynamic-parameters-and-positional-parameters-do-no

原始问题

我希望能够在包含静态和动态参数的 PowerShell 函数中指定位置参数。例如我有

function Test-Positional{
[CmdletBinding(PositionalBinding=$false)]
param(
    [Parameter(Mandatory=$false,Position=3)][string]$Param4
)
dynamicparam {
    $paramDictionary = new-object -Type System.Management.Automation.RuntimeDefinedParameterDictionary

    $paramname1 = "Param1"
    $values1 = 'some','list','of','values' #would normally get these dynamically
    $attributes1 = new-object System.Management.Automation.ParameterAttribute
    $attributes1.ParameterSetName = "__AllParameterSets"
    $attributes1.Mandatory = $true
    $attributes1.Position = 0
    $attributeCollection1 = new-object -Type System.Collections.ObjectModel.Collection[System.Attribute]
    $attributeCollection1.Add($attributes1)
    $ValidateSet1 = new-object System.Management.Automation.ValidateSetAttribute($values1)
    $attributeCollection1.Add($ValidateSet1)
    $dynParam1 = new-object -Type System.Management.Automation.RuntimeDefinedParameter($paramname1, [string], $attributeCollection1)

    $paramname2 = "Param2"
    $values2 = 'another','list','like','before'
    $attributes2 = new-object System.Management.Automation.ParameterAttribute
    $attributes2.ParameterSetName = "__AllParameterSets"
    $attributes2.Mandatory = $true
    $attributes2.Position = 1
    $attributeCollection2 = new-object -Type System.Collections.ObjectModel.Collection[System.Attribute]
    $attributeCollection2.Add($attributes2)
    $ValidateSet2 = new-object System.Management.Automation.ValidateSetAttribute($values2)
    $attributeCollection2.Add($ValidateSet2)
    $dynParam2 = new-object -Type System.Management.Automation.RuntimeDefinedParameter($paramname2, [string], $attributeCollection2)

    $paramname3 = "Param3"
    $values3 = 'yet','another','list'
    $attributes3 = new-object System.Management.Automation.ParameterAttribute
    $attributes3.ParameterSetName = "__AllParameterSets"
    $attributes3.Mandatory = $true
    $attributes3.Position = 2
    $attributeCollection3 = new-object -Type System.Collections.ObjectModel.Collection[System.Attribute]
    $attributeCollection3.Add($attributes3)
    $ValidateSet3 = new-object System.Management.Automation.ValidateSetAttribute($values3)
    $attributeCollection3.Add($ValidateSet3)
    $dynParam3 = new-object -Type System.Management.Automation.RuntimeDefinedParameter($paramname3, [string], $attributeCollection3)

    $paramDictionary.Add($paramname1, $dynParam1)
    $paramDictionary.Add($paramname2, $dynParam2)
    $paramDictionary.Add($paramname3, $dynParam3)
    return $paramDictionary
}

process{
   $PSBoundParameters.Param1
   $PSBoundParameters.Param2
   $PSBoundParameters.Param3
   $PSBoundParameters.Param4
}
}

但如果我 运行 PS C:\Windows\System32\inetsrv> Test-Positional 'list' 'another' 'yet' 'so' 我收到错误:

Test-Positional : Cannot validate argument on parameter 'Param1'. The argument "another" does not belong to the set "some,list,of,values" specified by the ValidateSet attribute. Supply an argument that is in the set and then try the command again. At line:1 char:20 + Test-Positional list another yet so + ~~~~~~~ + CategoryInfo : InvalidData: (:) [Test-Positional], ParameterBindingValidationException + FullyQualifiedErrorId : ParameterArgumentValidationError,Test-Positional

如果我从静态参数($param4)中删除 Position=3 属性,它不会抛出这个,这很好,除非我不能将它用作位置参数,我必须直接命名它.如果我保留 Position=3 并删除 PositionalBinding=$false

,我会得到同样的错误

是不是不能让静态和动态参数都成为位置参数?还是我在这里遗漏了一些明显的东西?

位置与相同类型的参数有关。所以静态参数会尊重其他静态参数的位置,动态参数会尊重其他动态参数的位置,但是静态参数会先消耗参数,动态参数会消耗剩下的。据我所知,唯一的例外是如果您使用 ValueFromRemainingArguments=$true 的参数属性,这会强制该特定参数成为最后一个参数。所以,如果你真的只有 1 个静态参数你想在动态参数之后出现,你可以设置 ValueFromRemainingArguments=$true 并且它会按照你的期望运行。如果您有其他静态参数,无论您指定的位置晚于动态参数的位置,它们仍然会出现在动态参数之前。

在我看来你发现了一个错误,我鼓励你在 PowerShell UserVoice 网站上为此提交一个错误:https://windowsserver.uservoice.com/forums/301869-powershell

在我看来,他们应该要么更新文档以声明在统计参数定位之后评估动态参数定位,要么更正语法部分 Get-Help 是 运行 而不是 function/script ,或相应地更新行为,以便在动态和静态参数中都尊重位置。我自己更喜欢后者,但这可能涉及不可行的引擎更改。

如果您确实创建了一个错误,请提供一个 link 以便其他人可以找到它并投票给它(这样它就会引起注意并得到修复!)。