Принятие необязательного параметра только как названное, а не позиционное

Я пишу PowerShell script, который является оберткой для .exe. Я хочу иметь необязательные параметры script и передать остальные непосредственно в exe. Здесь тест script:

param (
    [Parameter(Mandatory=$False)] [string] $a = "DefaultA"
   ,[parameter(ValueFromRemainingArguments=$true)][string[]]$ExeParams   # must be string[] - otherwise .exe invocation will quote
)

Write-Output ("a=" + ($a) + "  ExeParams:") $ExeParams

Если я запускаю с именованным параметром, все отлично:

C:\ > powershell /command \temp\a.ps1 -a A This-should-go-to-exeparams This-also
a=A  ExeParams:
This-should-go-to-exeparams
This-also

Однако, если я пытаюсь пропустить мой параметр, ему присваивается первый неназванный параметр:

C:\ > powershell /command \temp\a.ps1 This-should-go-to-exeparams This-also
a=This-should-go-to-exeparams  ExeParams:
This-also

Я бы ожидал:

a=DefaultA ExeParams:
This-should-go-to-exeparams
This-also

Я попытался добавить Position=0 к параметру, но это дает тот же результат.

Есть ли способ достичь этого?
Может быть, другая схема параметров?

Ответ 1

По умолчанию все параметры функции являются позиционными. Windows PowerShell присваивает номера позиций параметрам в том порядке, в котором параметры объявлены в функции. Чтобы отключить эту функцию, установите для параметра PositionalBinding атрибута CmdletBinding значение $False.

посмотрите at Как отключить привязку позиционных параметров в PowerShell

function Test-PositionalBinding
{
    [CmdletBinding(PositionalBinding=$false)]
    param(
       $param1,$param2
    )

    Write-Host param1 is: $param1
    Write-Host param2 is: $param2
}

Ответ 2

Основной ответ по-прежнему работает в версии 5 (в соответствии с комментариями, возможно, он некоторое время не работал в версии 2).

Есть еще один вариант: добавить Position в параметр ValueFromRemainingArgs.

Пример CommandWrapper.ps1:

param(
    $namedOptional = "default",
    [Parameter(ValueFromRemainingArguments = $true, Position=1)]
    $cmdArgs
)

write-host "namedOptional: $namedOptional"
& cmd /c echo cmdArgs: @cmdArgs

Образец вывода:

>commandwrapper hello world
namedOptional: default
cmdArgs: hello world

Это похоже на то, что PowerShell присваивает позиции параметров первому параметру с назначенной позицией.