Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

Let's say I have this function :

function Foo{
    [CmdLetBinding()]
    param(
        [Parameter(Mandatory=$true,ParameterSetName="A",Position=0)] 
        [Parameter(Mandatory=$true,ParameterSetName="both",Position=0)] 
        [int]
        $A,

        [Parameter(Mandatory=$true,ParameterSetName="B",Position=0)] 
        [Parameter(Mandatory=$true,ParameterSetName="both",Position=1)] 
        [int]
        $B
    )

    Write-Host $PsCmdlet.ParameterSetName

}

I expect this method to expect either A, or B or both. Never none.

However, if I call this :

Foo -A 1 -B 2 # outputs "both" as expected
Foo -B 3 # error
Foo -A 4 # error

The error I get is :

Foo : Parameter set cannot be resolved using the specified named parameters.
At c:\pathto:75 char:4
+ Foo <<<<  -B 3
    + CategoryInfo          : InvalidArgument: (:) [Foo], ParameterBindingException
    + FullyQualifiedErrorId : AmbiguousParameterSet,Foo

Foo : Parameter set cannot be resolved using the specified named parameters.
At c:\pathto.ps1:76 char:4
+ Foo <<<<  -A 4
    + CategoryInfo          : InvalidArgument: (:) [Foo], ParameterBindingException
    + FullyQualifiedErrorId : AmbiguousParameterSet,Foo

I troubled, because as you can see, I explicitly specify the parameters' name.

How should I write my function to works as expected?

share|improve this question

1 Answer 1

up vote 3 down vote accepted

You probably want to implement parameter checking in your function then. MS says that Parameter sets have to have one parameter that is unique to its parameter set. So, each parameter set must have one parameter that does not belong to any other parameter set, which is the reason for your error when trying to call the function w/ only one parameter, it doesn't know which parameter set to assign b/c the parameter supplied is not unique to a particular parameter set. I came close with

 function Foof{
[CmdLetBinding(DefaultParameterSetName="None")]
param(

    [Parameter(Mandatory=$false,ParameterSetName="A")]
    [Parameter(Position=0)]
    [int]
    $A,

    [Parameter(Mandatory=$false,ParameterSetName="B")]
    [Parameter(Mandatory=$false,ParameterSetName="both")]  
    [Parameter(Position=1)]
    [int]
    $B,

    [Parameter(Mandatory=$false,ParameterSetName="both")]  
    [int]
    $C=$true

)

Write-Host $PsCmdlet.ParameterSetName
write-host "A=$A and B=$B and C=$C"

}

I thought that assigning $C a default value would give your expected behavior, but it doesn't b/c the parameter has to be explicitly declared when calling the function.

You'll notice I set the DefaultParameterSetName to "None". What this does is give you a fast was to check for the case if neither parameters were submitted.

You could do something like check if $PsCmdlet.ParameterSetName -eq "None" then Read-Host whatever variable you want supplied, or just output an error that says either variable a or b should be supplied.

http://technet.microsoft.com/en-us/library/hh847743.aspx

share|improve this answer
    
I ended by removing the parameter set feature. In my function, I start now by a parameter check as you suggested : if((-Not $A) -and (-not $b)) { throw "Did you read the documentation? No? Shame on you!*" } –  Steve B Jan 10 '13 at 8:32

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.