Cmdlet Parameter Sets
Windows PowerShell uses the concept of parameter sets to enable you to write a single cmdlet that can perform different actions for different scenarios. Parameter sets allow you to expose different parameters to the user and to return different information based on the parameters specified by the user.
Get-EventLog Parameter Sets
For example, the Get-EventLog cmdlet (provided by Windows PowerShell) returns different information when the user specifies the List or LogName parameter. If the List parameter is specified, the cmdlet returns information about the log files themselves but not the event information they contain. If the LogName parameter is specified, the cmdlet returns information about the events in a specific event log. The List and LogName parameters identify two separate parameter sets.
Unique Parameter
Each parameter set must have a unique parameter that the Windows PowerShell runtime can use to expose the appropriate parameter set. If possible, the unique parameter should be a mandatory parameter. When a parameter is mandatory, the user is forced to specify the parameter, and the Windows PowerShell runtime can use that parameter to identify the parameter set to use. The unique parameter cannot be mandatory if your cmdlet is designed to be run without specifying any parameters.
Multiple Parameter Sets
In the following illustration, the left column shows three valid parameter sets. Parameter A is unique to the first parameter set, parameter B is unique to the second parameter set, and parameter C is unique to the third parameter set. However, in the right column, the parameter sets do not have a unique parameter.
Parameter Set Requirements
The following requirements apply to all parameter sets.
-
Each parameter set must have at least one unique parameter. If possible, make this parameter a mandatory parameter.
-
A parameter set that contains multiple positional parameters must define unique positions for each parameter. No two positional parameters can specify the same position.
-
Only one parameter in a set can declare the ValueFromPipeline keyword with a value of true. Multiple parameters can define the ValueFromPipelineByPropertyName keyword with a value of true.
-
If no parameter set is specified for a parameter, the parameter belongs to all parameter sets.
Default Parameter Sets
When multiple parameter sets are defined, you can use the DefaultParameterSetName keyword of the Cmdlet attribute to specify the default parameter set. Windows PowerShell uses the default parameter set if it cannot determine the parameter set to use based on the information provided by the command. For more information about the Cmdlet attribute, see Cmdlet Attribute Declaration.
Declaring Parameter Sets
To create a parameter set, you must specify the ParameterSetName keyword when you declare the Parameter attribute for every parameter in the parameter set. For parameters that belong to multiple parameter sets, add a Parameter attribute for each parameter set. This allows you to define the parameter differently for each parameter set. For example, you can define a parameter as mandatory in one set and optional in another. However, each parameter set must contain one unique parameter.
In the following example, the UserName parameter is the unique parameter of the Test01 parameter set, and the ComputerName parameter is the unique parameter of the Test02 parameter set. The SharedParam parameter belongs to both sets and is mandatory for the Test01 parameter set but optional for the Test02 parameter set.
[Parameter(Position = 0, Mandatory = true, ParameterSetName = "Test01")] public string UserName { get { return userName; } set { userName = value; } } private string userName; [Parameter(Position = 0, Mandatory = true, ParameterSetName = "Test02")] public string ComputerName { get { return computerName; } set { computerName = value; } } private string computerName; [Parameter(Mandatory= true, ParameterSetName = "Test01")] [Parameter(ParameterSetName = "Test02")] public string SharedParam { get { return sharedParam; } set { sharedParam = value; } } private string sharedParam;
- 1/31/2012
- NutSoft
- 3/1/2012
- FOREVER PINK
From: http://blogs.msdn.com/b/powershell/archive/2008/12/23/powershell-v2-parametersets.aspx
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]
- 11/18/2010
- JeremyPack