Как указать статические и динамические позиционные параметры в Powershell?

РЕДАКТИРОВАТЬ

Согласно предложению Безумного Техника, я отправил отчет об ошибке для этого на сайте 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: Невозможно проверить аргумент параметра "Param1". Аргумент "other" не принадлежит набору "some, list, of, values", указанному атрибутом ValidateSet. Укажите аргумент в наборе, а затем повторите команду. В строке:1 символ:20 + список Test-Positional еще один, так что + ~~~~~~~ + CategoryInfo: InvalidData: (:) [Test-Positional], ParameterBindingValidationException + FullyQualifiedErrorId: ParameterArgumentValidationError,Test-Positionalal

Это не бросает это, если я удаляю Position=3 атрибут из статического параметра ($param4), что нормально, за исключением того, что я не могу использовать его в качестве позиционного параметра, я должен назвать его напрямую. Я получаю ту же ошибку, если я продолжаю Position=3 и удалить PositionalBinding=$false

Разве невозможно, чтобы как статические, так и динамические параметры были позиционными параметрами? Или я что-то упускаю здесь очевидное?

1 ответ

Решение

Положение работает по отношению к параметрам того же типа. Таким образом, статические параметры будут учитывать положение других статических параметров, а динамические параметры будут уважать положение других динамических параметров, но статические параметры будут в первую очередь использовать аргументы, а динамические параметры будут использовать все, что осталось. Единственное исключение, о котором я знаю, - это если вы используете атрибут параметра ValueFromRemainingArguments=$true, что заставляет этот конкретный параметр быть последним. Итак, если у вас действительно есть только 1 статический параметр, который вы хотите использовать после динамических параметров, вы можете установить ValueFromRemainingArguments=$true и он будет вести себя, как вы хотите. Если у вас есть другие статические параметры, они все равно будут предшествовать динамическим параметрам, независимо от того, указали ли вы позицию позже, чем у динамических параметров.

Мне кажется, что вы нашли ошибку, и я бы посоветовал вам сообщить об этом на сайте PowerShell UserVoice: https://windowsserver.uservoice.com/forums/301869-powershell

По моему мнению, они должны либо обновить документацию, чтобы заявить, что динамическое позиционирование параметра оценивается после позиционирования параметра stat, и исправить синтаксический раздел, когда Get-Help запускается против функции / скрипта или обновляет поведение соответствующим образом, чтобы позиции учитывались как по динамическим, так и по статическим параметрам. Я бы предпочел последний сам, но это может включать изменения двигателя, которые неосуществимы.

Если вы создали ошибку, пожалуйста, предоставьте ссылку на нее, чтобы другие могли ее найти и проголосовать за нее (чтобы она привлекла внимание и была исправлена!).

Другие вопросы по тегам