2
votes

I am putting together a set of tools for internal account management. This particular cmdlet will prep an account for a transfer out, which includes an option to remove or retain their groups. My Param statement has become quite lengthy and has ended up with 6 parameter sets to cover every scenario. All combinations of parameters are working except for one. Here is my code:

function Move-AccountOut {

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

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

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

        [Parameter(ParameterSetName='TransferHomeDrive', Position=3)]
        [Parameter(ParameterSetName='RetainGroupsWTran', Position=3)]
        [Parameter(ParameterSetName='RemoveFromAllGroupsWTran', Position=3)]
        [switch]$TransferHomeDrive,

        [Parameter(ParameterSetName='TransferHomeDrive', Mandatory=$True, Position=4)]
        [Parameter(ParameterSetName='RetainGroupsWTran', Mandatory=$True, Position=4)]
        [Parameter(ParameterSetName='RemoveFromAllGroupsWTran', Mandatory=$True, Position=4)]
        [string]$OldServer,

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

Which will generate the following Get-Help output:

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

The parameter I am having trouble with is the bottom one (transfer only). I can run the command with username, username+retain, username+remove, username+retain+transfer and username+remove+transfer. But transfer without a retain or remove does not work. When run, it throws the following error:

Move-AccountOut : Parameter set cannot be resolved using the specified named parameters.
At line:33 char:1
+ Move-AccountOut -Username X -TransferHomeDrive -OldServer X -NewServer Y
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [Move-AccountOut], ParameterBindingException
    + FullyQualifiedErrorId : AmbiguousParameterSet,Move-AccountOut

I can't figure out why, given that it appears to be a valid parameter set according to my Get-Help output.

1
Try doing a trace: Trace-Command -Name ParameterBinding -Expression { Move-AccountOut -Username X -TransferHomeDrive -OldServer X -NewServer Y } -PSHost and post the output. - briantist

1 Answers

2
votes

Thank you for the output, here is the key (emphasis mine):

Remaining valid parameter set: RetainGroupsWTran
Remaining valid parameter set: RemoveFromAllGroupsWTran
Remaining valid parameter set: TransferHomeDrive

This happens after all parameters have been bound, and it shows that there are 3 valid parameter sets remaining.

TransferHomeDrive is the parameter set you want.

So why are the other ones there?

RetainGroupsWTran should only be possible if -RetainGroups is specified, and RemoveFromAllGroupsWTran should only be possible if -RemoveFromAllGroups is specified.

However, you can also see in the Get-Help output that there is no parameter set where those switches are mandatory, and this is the problem.

Your updated definition looks like the following:

function Move-AccountOut {

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

        [Parameter(ParameterSetName='RetainGroups',Position=2)]
        [Parameter(Mandatory=$true,ParameterSetName='RetainGroupsWTran',Position=2)]
        [switch]$RetainGroups,

        [Parameter(ParameterSetName='RemoveFromAllGroups',Position=2)]
        [Parameter(Mandatory=$true,ParameterSetName='RemoveFromAllGroupsWTran',Position=2)]
        [switch]$RemoveFromAllGroups,

        [Parameter(ParameterSetName='TransferHomeDrive', Position=3)]
        [Parameter(ParameterSetName='RetainGroupsWTran', Position=3)]
        [Parameter(ParameterSetName='RemoveFromAllGroupsWTran', Position=3)]
        [switch]$TransferHomeDrive,

        [Parameter(ParameterSetName='TransferHomeDrive', Mandatory=$True, Position=4)]
        [Parameter(ParameterSetName='RetainGroupsWTran', Mandatory=$True, Position=4)]
        [Parameter(ParameterSetName='RemoveFromAllGroupsWTran', Mandatory=$True, Position=4)]
        [string]$OldServer,

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

I've made them mandatory within the parameter sets that were showing up in the trace output.

I think that you should also make them mandatory in the RetainGroups and RemoveFromAllGroups parameter sets as well, but it's not shown above.