Reputation: 47437
Providing I have a three switch parameters
param(
[parameter(Mandatory=$false] [switch] $i,
[parameter(Mandatory=$false] [switch] $ir,
[parameter(Mandatory=$false] [switch] $iur
)
and only ONE of them is allowed, what is the best way to do this? If I use what's above, all three switches can be added as a parameter on a single call (undesirable).
> invoke-aspnetregiis -i -ir -iur # bad
I originally used a ValidateSet
on a [string]
[parameter(Mandatory=$false, ValidateSet('-i', '-ir', '-iur'))] [string] $arg
but then the call looks funny
invoke-aspnetregiis '-i' # notice the single quotes.
I prefer it too read
invoke-aspnetregiis -i # to mimic the native call
The best I've come up with so far is to use ParameterSetNames
[parameter(Mandatory=$false, ParameterSetName='i')] [switch] $i,
[parameter(Mandatory=$false, ParameterSetName='ir')] [switch] $ir,
[parameter(Mandatory=$false, ParameterSetName='iur')] [switch] $iur,
switch($PsCmdlet.ParameterSetName){
'i' {$argument = '-i'}
'ir' {$argument = '-ir'}
'iur' {$argument = '-iur'}
default {$argument = '-i'}
}
essentially making the actual switch irrelevant.
Is there a better way to accomplish this in Powershell?
Upvotes: 0
Views: 4821
Reputation: 11
the best can be use the validate scrip
[Parameter(Mandatory=$false)][ValidateScript({-not ($descendente -or $aleatorio )})][Switch]$ascendente,
[Parameter(Mandatory=$false)][ValidateScript({-not ($ascendente -or $aleatorio )})][Switch]$descendente,
[Parameter(Mandatory=$false)][ValidateScript({-not ($ascendente -or $descendente)})][Switch]$aleatorio
so powershell will throw the error
Upvotes: 1
Reputation: 200523
Parameter sets is what you'd normally use for something like this. If you name the parameter sets after the parameters you can even simplify passing the parameter to the actual command you're calling:
[CmdletBinding(DefaultParameterSetName='-i')]
Param(
[Parameter(ParameterSetName='-i',Mandatory=$false)][Switch]$i,
[Parameter(ParameterSetName='-ir',Mandatory=$false)][Switch]$ir,
[Parameter(ParameterSetName='-iur',Mandatory=$false)][Switch]$iur
)
& yourcommand $PSCmdlet.ParameterSetName
There are, of course, other options as well, like building your own logic for ensuring that just one out of the three parameters is provided:
Param(
[Parameter(Mandatory=$false)][Switch]$i,
[Parameter(Mandatory=$false)][Switch]$ir,
[Parameter(Mandatory=$false)][Switch]$iur
)
if (1 -ne $i.IsPresent + $ir.IsPresent + $iur.IsPresent) {
'Usage: script.ps1 {-i|-ir|iur}'
exit 1
}
However, as @mikez pointed out in the comments, the command/script help will not automatically show that the parameters cannot be used in conjunction with each other:
PS C:\> .\test_paramset.ps1 -?
test_paramset.ps1 [-a] [<CommonParameters>]
test_paramset.ps1 [-b] [<CommonParameters>]
test_paramset.ps1 [-c] [<CommonParameters>]
PS C:\> .\test_no_paramset.ps1 -?
test_no_paramset.ps1 [-a] [-b] [-c] [<CommonParameters>]
thus making the alternative approach a little less user-friendly.
Upvotes: 2
Reputation: 81052
Nothing about the ParameterSetName usage makes the switches irrelevant. They are how the user picked the mode in the first place.
You don't have to use the same name for the ParameterSetName as the switch name.
You don't have to use $argument
and can just use the switch name if you cant.
You can just use the switch name and ignore ParameterSetName
(since powershell has ensured you only get one switch among the sets already).
You could also manually validate the arguments given if you wanted to.
I don't know of any other way (but I'm not a powershell expert either).
Upvotes: 0