Automating the world one-liner at a time…
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
This is *very* cool. I'll make heavy use of this feature.
Other languages use overloading for this type of feature. What made you decide to "pack" all into one function? Will overloading be available as an alternative to keep code more readable?
@alexander
I didn't follow that. Can you post an example of what you would like to work?
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
Sure!
I'll email it to you, you can decide if you want to blog it.
Alex
Please remember that each parameter set must have at least one parameter that is unique...it does not belong to any other parameter set. This unique parameter should be mandatory, unless you are writing an advanced function (or cmdlet) that can be called without specifying any parameters.