Marc M.
Marc M.

Reputation: 57

PowerShell : args and named parameter

I have a PS script I call from a Windows shortcut. I drop on it several files or directories, and it works fine. I would like to add some named parameters (let's call them : -Param1 and -Param2), optional, that can be used, of course, only from PowerShell Prompt.

param (
    [switch]$CreateShortcut
)

A switch parameter works.

But, if I add a string parameter :

param (
    [switch]$CreateShortcut,
    [string]$Param1
)

Of course, it does not work anymore when I call my script thru the Windows shortcut : $Param1 receive the first file.

Is there a solution ?

Thanks

Upvotes: 1

Views: 1773

Answers (1)

mklement0
mklement0

Reputation: 437062

When you drop files/folders on a shortcut file, their full paths are passed as individual, unnamed arguments to the shortcut's executable (script).

PowerShell allows you to collect such unnamed arguments in a single, array-valued parameter, by declaring it as ValueFromRemainingArguments:

[CmdletBinding(PositionalBinding=$false)]
param (
    [switch] $CreateShortcut,
    # Collect all unnamed arguments in this parameter:
    [Parameter(ValueFromRemainingArguments)]
    [string[]] $FilesOrFolders
)
  • [CmdletBinding(PositionalBinding=$false)] ensures that any parameters not explicitly marked with a Position property must be passed as named arguments (i.e., the argument must be preceded by the name of the target parameter, e.g. -Path foo).

    • This isn't necessary to support [switch] parameters, because they are implicitly named-only, but it allows you to support additional, non-[switch] parameters that can be bound by explicit invocation (only).
  • Alternatively, if you do not need support for additional predeclared non-switch parameters, you can omit [CmdletBinding(PositionalBinding=$false)] and the $FilesOrFolders parameter declaration and access any arguments that do not bind to predeclared parameters via the automatic $args variable.

    • Generally, note that use of a [Parameter()] attribute on any of the predeclared parameters would make $args unavailable, as the presence of [CmdletBinding()] does.

    • The reason is that the use of either attribute makes a script or function an advanced one, i.e., makes it cmdlet-like, and therefore disallows passing arguments that do not bind to declared parameters; to put it differently: $args is then by definition always empty (an empty array).

    • Advanced scripts or functions automatically gain additional features, notably support for common parameters such as -Verbose.

Upvotes: 5

Related Questions