Reputation: 179
I'm writing a powershell script which has several parameters
param(
[Parameter(Mandatory=$true, Position=0)]
[ValidateSet('a', 'b', 'c', 'd')]
[string] $abcd,
[Parameter(Mandatory=$true)] [string] $mandatory1,
[Parameter(Mandatory=$true)] [string] $mandatory2,
[Parameter()] $optional1=$false,
[Parameter()] $optional2=$false,
[Parameter()] $defaulted1=256,
[Parameter()] $defaulted2=30,
[Parameter()] [string] $defaulted3='defaulted3',
[Parameter(ValueFromRemainingArguments=$true)] [string[]] $rest
)
However, when I try to call it, some parameters are being assigned to the optionals/defaults instead of to $rest.
.\my-script `
-abcd a `
-mandatory1 value1 `
-mandatory2 value2 `
-optional1 value3 `
-optional2 value4 `
-rest `
foo `
bar `
baz
my script prints
optional1 is value3
optional2 is value4
defaulted1 is bar
defaulted2 is baz
rest is foo
So it looks like Powershell prefers to assign things by position to arguments even if they have default values, over assigning them to the ValueFromRemainingArguments param.
Is there a way to change this behavior and set an optional parameter's value by name only?
I tried using How to specify a non-positional parameter in a PowerShell script? and Powershell non-positional, optional params but either I did it wrong or it doesn't work the way I thought it would.
Upvotes: 1
Views: 763
Reputation: 25021
Add [CmdletBinding(PositionalBinding=$false)]
before the param
keyword at the top of the script. See Require and test for named arguments only
Here is an example of the parameter attribute being applied to your code:
function test {
[cmdletbinding(PositionalBinding=$false)]
param(
[Parameter(Mandatory=$true)]
[ValidateSet('a', 'b', 'c', 'd')]
[string] $abcd,
[Parameter(Mandatory=$true)] [string] $mandatory1,
[Parameter(Mandatory=$true)] [string] $mandatory2,
[Parameter()] $optional1=$false,
[Parameter()] $optional2=$false,
[Parameter()] $defaulted1=256,
[Parameter()] $defaulted2=30,
[Parameter()] [string] $defaulted3='defaulted3',
[Parameter(ValueFromRemainingArguments=$true)] [string[]] $rest
)
$rest
}
test -abcd "a" -mandatory1 "hi" -mandatory2 "hi" "foo" "bar"
foo
bar
test -abcd "a" -mandatory1 "hi" -mandatory2 "hi" -rest foo,bar,baz
foo
bar
baz
Upvotes: 1