PowerShell V2: ParameterSets

PowerShell Team

One of the great benefits of PowerShell V2 Advanced Functions is the ease in which you can support parametersets.  ParameterSets are, well, different SETS of valid parameters.  For instance you can say:
Get-Process -id 0

Get-Process -Name *ss

Those are 2 different parametersets for the Get-Process cmdlet.  Here is an example of how you would code parametersets using advanced functions:

function test-param
{
param(
[Parameter(ParameterSetName=”p1″,Position=0)]
[DateTime]
$d,

[Parameter(ParameterSetName=”p2″, Position=0)]
[int]
$i
)
    switch ($PsCmdlet.ParameterSetName)
    {
    “p1”  { Write-Host $d; break}
    “p2”  { Write-Host $i; break}
    }
}

Now the question becomes – which Parameterset is used?  Let’s experiment.  Clearly you can specify which parameter you want and the right thing will happen:

PS> test-param -d (get-Date)
12/23/2008 3:25:25 PM
PS> test-param -i 42
42

But what happens when it is ambiguous?  Where this is where the magic of PowerShell kicks in.  PowerShell uses the types of the input to determine which one you want.  If you specified a DateTime you probably want the p1 parameterset and if you specified a INT you probably want the p2 parameterset.

PS> test-param (get-Date)
12/23/2008 3:37:01 PM
PS> test-param 42
42

This almost always does exactly what you want but if it doesn’t, you can always say what you want and you’ll get it (it is just a mechanism to relieve you of work!).

PS> test-param -d 42
1/1/0001 12:00:00 AM

(That is the DATETIME corresponding to 42 TICKs of the clock!  Was that really what you wanted? 🙂 )

So now comes the interesting part.  What if the parametersets are ambiguous.  Let’s redo the script and make both parameters be STRINGs and then convert to DATETIME and INT in the script and see what happens.

function test-param
{
param(
[Parameter(ParameterSetName=”p1″,Position=0)]
[String]
$d,

[Parameter(ParameterSetName=”p2″, Position=0)]
[String]
$i
)
    switch ($PsCmdlet.ParameterSetName)
    {
    “p1”  { Write-Host ([DateTime]$d); break}
    “p2”  { Write-Host ([INT]$i); break}
    }
}

PS> test-param -i “42”
42

PS> test-param “42”
test-param : Parameter set cannot be resolved using the specified named par
ameters.
At line:1 char:11
+ test-param <<<<  “42”
    + CategoryInfo          : InvalidArgument: (:) [test-param], Parameter
   BindingException
    + FullyQualifiedErrorId : AmbiguousParameterSet,test-param

If you don’t specify which one you want, it is ambiguous.  But let’s say that as the script author, you know that 9 out of 10 times people are going to want the p2 parameterset.  Do you really want to make people type in the parametername every time just to get around this ambiguity?  Wouldn’t it be great if the PowerShell team thought about such a circumstance and give you a mechanism to specify which parameterset to pick if things were ambiguous?

OH WAIT – they did!

function test-param
{
[CmdletBinding(DefaultParametersetName=”p2″)]
param(
[Parameter(ParameterSetName=”p1″,Position=0)]
[String]
$d,

[Parameter(ParameterSetName=”p2″, Position=0)]
[String]$i
)
    switch ($PsCmdlet.ParameterSetName)
    {
    “p1”  { Write-Host ([DateTime]$d); break}
    “p2”  { Write-Host ([INT]$i); break}
    }
}

PS> test-param 42
42

Party on!

Jeffrey Snover [MSFT]
Windows Management Partner Architect
Visit the Windows PowerShell Team blog at:    http://blogs.msdn.com/PowerShell
Visit the Windows PowerShell ScriptCenter at:  http://www.microsoft.com/technet/scriptcenter/hubs/msh.mspx

0 comments

Discussion is closed.

Feedback usabilla icon