18

I have this script that can be called in two ways:

MyScript -foo path\to\folder

or

MyScript -bar path\to\folder

(That is, I can either pass a switch plus a folder or a string argument plus a folder.)

I have tried to put parameter declarations into my script as to reflect that syntax:

param(
  [parameter(Mandatory=$false)] [switch]$foo,
  [parameter(Mandatory=$false)] [String]$bar,
  [parameter(Mandatory=$true)]  [System.IO.FileInfo]$path
)

But then I have to pass path explicitly to invoke the script:

MyScript -l -path path\to\folder

So (how) can I do that making both bar and path positional parameters?

Note: If I have picked an extraordinarily stupid syntax for invoking the script, I can still change it.

2 Answers 2

28

A couple of things: You need to use parameter sets to tell PowerShell that there are mutually exclusive ways to invoke your script; that is to say, you cannot use the switch and the string at the same time. The sets also serve to allow you to set the position of both $bar and $filepath to be at index 0. Switches don't need to be positionally placed as they are not ambiguous to the binder and be placed anywhere. Also, at least one parameter in each set should be mandatory.

function test-set {
    [CmdletBinding(DefaultParameterSetName = "BarSet")]
    param(
        [parameter(
            mandatory=$true,
            parametersetname="FooSet"
        )]
        [switch]$Foo,

        [parameter(
            mandatory=$true,
            position=0,
            parametersetname="BarSet"
        )]
        [string]$Bar,

        [parameter(
            mandatory=$true,
            position=1
        )]
        [io.fileinfo]$FilePath
    )
@"
  Parameterset is: {0}
  Bar is: '{1}'
  -Foo present: {2}
  FilePath: {3}
"@ -f $PSCmdlet.ParameterSetName, $bar, $foo.IsPresent, $FilePath
}

The CmdletBinding attribute is needed to specify which parameter set should be the default if the function is invoked without parameters.

Here's the syntax help for the above configuration:

PS> test-set -?

NAME
    test-set

SYNTAX
    test-set [-Bar] <string> [-FilePath] <FileInfo>  [<CommonParameters>]

    test-set [-FilePath] <FileInfo> -Foo  [<CommonParameters>]

And here's the output for various invocations:

PS> test-set barval C:\temp\foo.zip
  Parameterset is: BarSet
  Bar is: 'barval'
  -Foo present: False
  FilePath: C:\temp\foo.zip

PS> test-set -foo c:\temp\foo.zip
  Parameterset is: FooSet
  Bar is: ''
  -Foo present: True
  FilePath: c:\temp\foo.zip

Hope this helps.

Sign up to request clarification or add additional context in comments.

1 Comment

Ok, so this did it, and it now all works beautifully. Thanks a lot!
0

As explained here you can specify the parameter position of your parameter.

[parameter(Position=0)]

1 Comment

But this won't allow the second calling syntax.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.