Как указать статические и динамические позиционные параметры в 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
запускается против функции / скрипта или обновляет поведение соответствующим образом, чтобы позиции учитывались как по динамическим, так и по статическим параметрам. Я бы предпочел последний сам, но это может включать изменения двигателя, которые неосуществимы.
Если вы создали ошибку, пожалуйста, предоставьте ссылку на нее, чтобы другие могли ее найти и проголосовать за нее (чтобы она привлекла внимание и была исправлена!).