I am building a function which will have three distinct parameter sets, and two of those sets will overlap with the third. The options would look like this:
You can also use [ValidateScript()]
, if have two Mandatory = false
parameters in all parameter sets, and you need to use them only together, e.g.:
function SomeFunction {
[CmdletBinding()]
Param(
[Parameter (Mandatory = $true,
ParameterSetName = "A")]
[Parameter (Mandatory = $true,
ParameterSetName = "B")]
[Parameter (Mandatory = $true,
ParameterSetName = "C")]
[switch]$Param1,
[Parameter (Mandatory = $true,
ParameterSetName = "A")]
[switch]$Param2,
[Parameter (Mandatory = $true,
ParameterSetName = "B")]
[string]$Param3,
[Parameter (Mandatory = $true,
ParameterSetName = "C")]
[string]$Param4,
[Parameter (Mandatory = $false,]
[ValidateScript({
if ($Param6) {
$True
}
else {
throw "This parameter will work only with parameter [Param6]"
}
}
)]
[string]$Param5,
[Parameter (Mandatory = $false)]
[ValidateScript({
if ($Param5) {
$True
}
else {
throw "This parameter will work only with parameter [Param5]"
}
}
)]
[string]$Param6
...
}
Ok, I think I understand this. The possible combinations you want are:
-RetainGroups
-RemoveFromAllGroups
-RetainGroups
plus -TransferHomeDrive
-RemoveFromAllGroups
plus -TransferHomeDrive
-UserName
-UserName
plus -TransferHomeDrive
I am assuming that -OldServer
and -NewServer
only apply when moving the home drive, so whenever you are moving the home drive, they are mandatory. If that is not the case, let me know.
So what you have here are 6 parameter sets. As powerful as powershell's parameter set magic is, there isn't a good way to say "these 2 switches are mutually exclusive but should also be available in all parameter sets" so you have to multiplex it and repeat every parameter set with one or the other.
function Move-AccountOut {
[CmdletBinding(DefaultParameterSetName='OnlyUser')]
Param(
[Parameter(
Mandatory=$True,
ValueFromPipeline=$True,
ValueFromPipelineByPropertyName=$True
)]
[string]
$Username,
[Parameter(
Mandatory=$True,
ParameterSetName='RetainOnly'
)]
[Parameter(
Mandatory=$True,
ParameterSetName='RetainAndTransfer'
)]
[switch]
$RetainGroups,
[Parameter(
Mandatory=$True,
ParameterSetName='RemoveOnly'
)]
[Parameter(
Mandatory=$True,
ParameterSetName='RemoveAndTransfer'
)]
[switch]
$RemoveFromAllGroups,
[Parameter(
Mandatory=$True,
ParameterSetName='RetainAndTransfer'
)]
[Parameter(
Mandatory=$True,
ParameterSetName='RemoveAndTransfer'
)]
[Parameter(
Mandatory=$True,
ParameterSetName='TransferOnly'
)]
[switch]
$TransferHomeDrive,
[Parameter(
Mandatory=$True,
ParameterSetName='RetainAndTransfer'
)]
[Parameter(
Mandatory=$True,
ParameterSetName='RemoveAndTransfer'
)]
[Parameter(
Mandatory=$True,
ParameterSetName='TransferOnly'
)]
[string]
$OldServer,
[Parameter(
Mandatory=$True,
ParameterSetName='RetainAndTransfer'
)]
[Parameter(
Mandatory=$True,
ParameterSetName='RemoveAndTransfer'
)]
[Parameter(
Mandatory=$True,
ParameterSetName='TransferOnly'
)]
[string]
$NewServer
)
}
The output of Get-Help Move-AccountOut
:
Move-AccountOut -Username <string> [<CommonParameters>] Move-AccountOut -Username <string> -RetainGroups -TransferHomeDrive -OldServer <string> -NewServer <string> [<CommonParameters>] Move-AccountOut -Username <string> -RetainGroups [<CommonParameters>] Move-AccountOut -Username <string> -RemoveFromAllGroups -TransferHomeDrive -OldServer <string> -NewServer <string> [<CommonParameters>] Move-AccountOut -Username <string> -RemoveFromAllGroups [<CommonParameters>] Move-AccountOut -Username <string> -TransferHomeDrive -OldServer <string> -NewServer <string> [<CommonParameters>]
If you want to make it less daunting, you might consider consolidating the remove and retain switches into a single parameter, something like this:
[Parameter(
Mandatory=$false # you can leave this out
)]
[ValidateSet(
'None',
'Retain',
'RemoveAll'
)]
[String]
$GroupAction = 'None'
This would reduce your parameter sets down to 2, and make your entire definition look like this:
function Move-AccountOut {
[CmdletBinding(DefaultParameterSetName='OnlyUser')]
Param(
[Parameter(
Mandatory=$True,
ValueFromPipeline=$True,
ValueFromPipelineByPropertyName=$True
)]
[string]
$Username,
[ValidateSet(
'None',
'Retain',
'RemoveAll'
)]
[String]
$GroupAction = 'None' ,
[Parameter(
Mandatory=$True,
ParameterSetName='TransferOnly'
)]
[switch]
$TransferHomeDrive,
[Parameter(
Mandatory=$True,
ParameterSetName='TransferOnly'
)]
[string]
$OldServer,
[Parameter(
Mandatory=$True,
ParameterSetName='TransferOnly'
)]
[string]
$NewServer
)
}
With the following Get-Help
output:
Move-AccountOut -Username <string> [-GroupAction <string> {None | Retain | RemoveAll}] [<CommonParameters>] Move-AccountOut -Username <string> -TransferHomeDrive -OldServer <string> -NewServer <string> [-GroupAction <string> {None | Retain | RemoveAll}] [<CommonParameters>]
I do want to point out that although that's simpler to define that doesn't mean it's better. It may be that you want to optimize your parameter sets for the caller which can be especially important if this is a function you plan on using interactively a lot from the shell, rather than calling from other scripts (and it seems like this may be the case).
So adding some complexity in the definition to make it easier to use might be the right thing to do.
By adding two more Parameter Sets you can do what you want. This is needed because you have 3 sets now, plus a non-set parameter (which technically puts it in the __AllParameterSets
set if I remember right). So that's 4 ways of doing it. You need 6 ways of doing it if I am reading your question correctly. You want all of the following options:
Move-AccountOut -Username <string> [<CommonParameters>]
Move-AccountOut -Username <string> [-RetainGroups] [-TransferHomeDrive] [-OldServer <string>] [-NewServer <string>] [<CommonParameters>]
Move-AccountOut -Username <string> [-RetainGroups] [<CommonParameters>]
Move-AccountOut -Username <string> [-RemoveFromAllGroups] [-TransferHomeDrive] [-OldServer <string>] [-NewServer <string>] [<CommonParameters>]
Move-AccountOut -Username <string> [-RemoveFromAllGroups] [<CommonParameters>]
Move-AccountOut -Username <string> -OldServer <string> -NewServer <string> [-TransferHomeDrive] [<CommonParameters>]
So we will add the RemoveFromAllGroupsWTran
and RetainGroupsWTran
Parameter Sets, add them both to $TransferHomeDrive
, $OldServer
, and $NewServer
(removing the other related set names from them), then add each to its respective switch parameter. It ends up looking like this:
function Move-AccountOut {
[CmdletBinding(DefaultParameterSetName='NoTransferHomeDrive')]
Param(
[Parameter(Mandatory=$True, ValueFromPipeline=$True, ValueFromPipelineByPropertyName=$True)]
[string]$Username,
[Parameter(ParameterSetName='RetainGroups')]
[Parameter(ParameterSetName='RetainGroupsWTran')]
[switch]$RetainGroups,
[Parameter(ParameterSetName='RemoveFromAllGroups')]
[Parameter(ParameterSetName='RemoveFromAllGroupsWTran')]
[switch]$RemoveFromAllGroups,
[Parameter(ParameterSetName='TransferHomeDrive', Mandatory=$False)]
[Parameter(ParameterSetName='RetainGroupsWTran')]
[Parameter(ParameterSetName='RemoveFromAllGroupsWTran')]
[switch]$TransferHomeDrive,
[Parameter(ParameterSetName='TransferHomeDrive', Mandatory=$True)]
[Parameter(ParameterSetName='RetainGroupsWTran')]
[Parameter(ParameterSetName='RemoveFromAllGroupsWTran')]
[string]$OldServer,
[Parameter(ParameterSetName='TransferHomeDrive', Mandatory=$True)]
[Parameter(ParameterSetName='RetainGroupsWTran')]
[Parameter(ParameterSetName='RemoveFromAllGroupsWTran')]
[string]$NewServer
)
}