Create an account

Very important

  • To access the important data of the forums, you must be active in each forum and especially in the leaks and database leaks section, send data and after sending the data and activity, data and important content will be opened and visible for you.
  • You will only see chat messages from people who are at or below your level.
  • More than 500,000 database leaks and millions of account leaks are waiting for you, so access and view with more activity.
  • Many important data are inactive and inaccessible for you, so open them with activity. (This will be done automatically)


Thread Rating:
  • 334 Vote(s) - 3.43 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Multiple parameter sets and PowerShell

#1
<!-- language-all: lang-powershell -->

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:

A B
A C
A (D E F)
A B (D E F)
A C (D E F)

To make it a little more clear, here is a partially completed version the function:

function Move-AccountOut {

[CmdletBinding(DefaultParameterSetName='NoTransferHomeDrive')]
Param(
[Parameter(Mandatory=$True, ValueFromPipeline=$True, ValueFromPipelineByPropertyName=$True)]
[string]$Username,

[Parameter(ParameterSetName='RetainGroups')]
[switch]$RetainGroups,

[Parameter(ParameterSetName='RemoveFromAllGroups')]
[switch]$RemoveFromAllGroups,

[Parameter(ParameterSetName='TransferHomeDrive', Mandatory=$False)]
[switch]$TransferHomeDrive,

[Parameter(ParameterSetName='TransferHomeDrive', Mandatory=$True)]
[string]$OldServer,

[Parameter(ParameterSetName='TransferHomeDrive', Mandatory=$True)]
[string]$NewServer
)
}

The purpose of the function is to automate the process of transferring out an AD account to another location within the company. `RetainGroups` would automatically retain the users groups when set, and `RemoveFromAllGroups` would automatically remove the user from their groups. The two switches should not be able to be used together. Additionally, if `TransferHomeDrive` is set, it will call a function to schedule a transfer using an internal tool.

To put it another way, `RetainGroups` and `RemoveFromAllGroups` should be a member of all parameter sets (similar to `Username`), but should not be able to be used together.

I have tried two ways. The first:

function Move-AccountOut {

[CmdletBinding(DefaultParameterSetName='NoTransferHomeDrive')]
Param(
[Parameter(Mandatory=$True, ValueFromPipeline=$True, ValueFromPipelineByPropertyName=$True)]
[string]$Username,

[Parameter(ParameterSetName='RetainGroups')]
[switch]$RetainGroups,

[Parameter(ParameterSetName='RemoveFromAllGroups')]
[switch]$RemoveFromAllGroups,

[Parameter(ParameterSetName='TransferHomeDrive', Mandatory=$False)]
[Parameter(ParameterSetName='RetainGroups')]
[Parameter(ParameterSetName='RemoveFromAllGroups')]
[switch]$TransferHomeDrive,

[Parameter(ParameterSetName='TransferHomeDrive', Mandatory=$True)]
[Parameter(ParameterSetName='RetainGroups')]
[Parameter(ParameterSetName='RemoveFromAllGroups')]
[string]$OldServer,

[Parameter(ParameterSetName='TransferHomeDrive', Mandatory=$True)]
[Parameter(ParameterSetName='RetainGroups')]
[Parameter(ParameterSetName='RemoveFromAllGroups')]
[string]$NewServer
)
}

Using this technique, retain and remove cannot be used together, but `OldServer` and `NewServer` are no longer mandatory. If I change them to:

[Parameter(ParameterSetName='TransferHomeDrive', Mandatory=$True)]
[Parameter(ParameterSetName='RetainGroups', Mandatory=$True)]
[string]$OldServer,

[Parameter(ParameterSetName='TransferHomeDrive', Mandatory=$True)]
[Parameter(ParameterSetName='RetainGroups', Mandatory=$True)]
[string]$NewServer

They will be mandatory, but it no longer cares whether `TransferHomeDrive` is set.

If I set it up the opposite way:

function Move-AccountOut {

[CmdletBinding(DefaultParameterSetName='NoTransferHomeDrive')]
Param(
[Parameter(Mandatory=$True, ValueFromPipeline=$True, ValueFromPipelineByPropertyName=$True)]
[string]$Username,

[Parameter(ParameterSetName='RetainGroups')]
[Parameter(ParameterSetName='TransferHomeDrive')]
[switch]$RetainGroups,

[Parameter(ParameterSetName='RemoveFromAllGroups')]
[Parameter(ParameterSetName='TransferHomeDrive')]
[switch]$RemoveFromAllGroups,

[Parameter(ParameterSetName='TransferHomeDrive', Mandatory=$False)]
[switch]$TransferHomeDrive,

[Parameter(ParameterSetName='TransferHomeDrive', Mandatory=$True)]
[string]$OldServer,

[Parameter(ParameterSetName='TransferHomeDrive', Mandatory=$True)]
[string]$NewServer
)
}

Then `OldServer` and `NewServer` will be mandatory, but `RetainGroups` and `RemoveFromAllGroups` can be used together. Additionally, if I use retain and remove together, then `OldServer` and `NewServer` become mandatory, but not when they are used on their own.

How do I make this work?
Reply

#2
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:

<!-- language-all: lang-psh -->

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
)
}
Reply

#3
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
...
}
Reply

#4
Ok, I think I understand this. The possible combinations you want are:

1. `-RetainGroups`
1. `-RemoveFromAllGroups`
1. `-RetainGroups` plus `-TransferHomeDrive`
1. `-RemoveFromAllGroups` plus `-TransferHomeDrive`
1. Only `-UserName`
1. `-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.

<!-- language-all: lang-powershell -->

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>]

# Simplifying It
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.
Reply



Forum Jump:


Users browsing this thread:
1 Guest(s)

©0Day  2016 - 2023 | All Rights Reserved.  Made with    for the community. Connected through