bacar
bacar

Reputation: 10091

Can I suppress parameter aliases?

Given this function and invocation:

function Foo($bar) { 
    Write-Host "bar=$bar, other args = $args"
}

Foo -b baz -quux quuux

Powershell will treat the -b argument as an alias for the $bar argument and print

bar=baz, other args = -quux quuux

I don't want it to do this! My function needs to work with both named arguments and arbitrary additional arguments; if one of those arbitrary arguments is -b, I don't want it assigned to $bar. That is, I want it to print:

bar=, other args = -b baz -quux quuux

Can I suppress the default parameter aliasing that powershell does?

I'm using powershell 2.0

Upvotes: 1

Views: 215

Answers (3)

Jason Shirk
Jason Shirk

Reputation: 8019

PowerShell has no way of disabling support for unambiguous prefix matching of parameters.

There are a few options though with various tradeoffs.

Option 1 - parse arguments yourself:

function foo {
    param()

    # $args has all of the parameters and arguments
}

This is more difficult for you to write, but solves the problem you hope to solve because you will completely own parameter/argument binding.

The other downside is no tab completion for parameters, at least not without some extra corresponding help in TabExpansion or TabExpansion2 (e.g. using a module like TabExpansion++ or PowerTab).

Note in this example you don't want cmdlet binding even if you have a parameter that is "value from remaining arguments" because cmdlet binding will add the common parameters and those parameters will be bound if an unambiguous prefix is used.

Option 2 - Require the caller to do something different

There are several cmdlets with a similar problem, e.g. Invoke-Command or Get-Command. Both accept an array of arguments. Users must quote parameters:

icm { param($a,$b) $b } -ArgumentList '-b','hello'

These cmdlets use -ArgumentList because they really must accept arbitrary arguments that might conflict with the cmdlet's arguments.

If your problem is more constrained, there might be another option, but it's requires some uncommonly used syntax and will still have problems with some parameters. An example:

function foo
{
    param([Parameter(ValueFromRemainingArguments=$true)]$ArgumentList)
    $ArgumentList
}

foo -- -A 1 -Ar 2 -Arg 3

The special token '--' tells PowerShell everything after is an argument. This way, arguments that look like parameters are treated as arguments.

This approach could be confusing if callers forget '--'.

Upvotes: 2

mjolinor
mjolinor

Reputation: 68301

You can stop the parser from interpreting the -b as a parameter alias by quoting it:

function Foo($bar) { 
    Write-Host "bar=$bar, other args = $args"
}

Foo '-b' baz -quux quuux

bar=-b, other args = baz -quux quuux

Upvotes: 2

alroc
alroc

Reputation: 28174

AFAIK, you can't have it both ways. You can use a "basic" function that exhibits the behavior you see here, or you can use an advanced function with named parameters which will validate the parameter names strictly.

"Arbitrary parameters" get really, really ugly and IMHO should be avoided for a number of reasons (some of which involve code security - could you end up executing unknown arbitrary code?).

Make Foo an advanced function, and make your "arbitrary" arguments a collection of Objects which is optional.

function Foo { 
[cmdletBinding()]
param (
    [Parameter(Mandatory=$True)]
    [string]$bar,
    [Parameter(Mandatory=$False)]
    [object[]]$args
)
    Write-Output "bar=$bar";
    # Test for $args here and process each item in it

}

Upvotes: 2

Related Questions