Multiple parameter sets and PowerShell

时间:2015-05-12 23:05:08

标签: 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:

 idtravel | travel | value  | status
    1          London   600 | Completed
    2          NY       1500| Planned 
    3          Lisbon   150 | Completed

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

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

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

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

I have tried two ways. The first:

Username

Using this technique, retain and remove cannot be used together, but 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 ) } and OldServer are no longer mandatory. If I change them to:

NewServer

They will be mandatory, but it no longer cares whether [Parameter(ParameterSetName='TransferHomeDrive', Mandatory=$True)] [Parameter(ParameterSetName='RetainGroups', Mandatory=$True)] [string]$OldServer, [Parameter(ParameterSetName='TransferHomeDrive', Mandatory=$True)] [Parameter(ParameterSetName='RetainGroups', Mandatory=$True)] [string]$NewServer is set.

If I set it up the opposite way:

TransferHomeDrive

Then 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 ) } and OldServer will be mandatory, but NewServer and RetainGroups can be used together. Additionally, if I use retain and remove together, then RemoveFromAllGroups and OldServer become mandatory, but not when they are used on their own.

How do I make this work?

3 个答案:

答案 0 :(得分:21)

好的,我想我理解这一点。您想要的可能组合是:

  1. -RetainGroups
  2. -RemoveFromAllGroups
  3. -RetainGroups-TransferHomeDrive
  4. -RemoveFromAllGroups-TransferHomeDrive
  5. -UserName
  6. -UserName-TransferHomeDrive
  7. 我假设-OldServer-NewServer仅在移动主驱动器时适用,因此无论何时移动主驱动器,它们都是强制性的。如果不是这样,请告诉我。

    所以你在这里有 6个参数集。与powershell的参数设置魔法一样强大,没有一种好的方式可以说"这两个开关是相互排斥的,但也应该在所有参数集中都可用#34;所以你必须多路复用它并用一个或另一个重复每个参数集。

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

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

    简化

    如果你想让它不那么令人生畏,你可以考虑将remove和retain开关合并为一个参数,如下所示:

    [Parameter(
        Mandatory=$false # you can leave this out
    )]
    [ValidateSet(
        'None',
        'Retain',
        'RemoveAll'
    )]
    [String]
    $GroupAction = 'None'
    

    这会将参数集减少到2,并使整个定义看起来像这样:

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

    使用以下Get-Help输出:

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

    我想指出的是,虽然定义更简单,但并不意味着它更好。您可能希望优化调用者的参数集,如果这是您计划从shell中交互使用的一个函数,而不是从其他脚本调用(和似乎可能是这种情况)。

    因此,在定义中添加一些复杂性以使其更易于使用可能是正确的做法。

答案 1 :(得分:8)

通过添加两个参数集,您可以执行所需的操作。这是必需的,因为你现在有3套,加上一个非设置参数(如果我没记错的话,技术上将它放在__AllParameterSets集中)。这是4种方法。如果我正确地阅读您的问题,您需要6种方法。您需要以下所有选项:

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

因此,我们将添加RemoveFromAllGroupsWTranRetainGroupsWTran参数集,将它们添加到$TransferHomeDrive$OldServer$NewServer(删除其他相关集)从它们的名称),然后将每个添加到其各自的开关参数。最终看起来像这样:

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

答案 2 :(得分:1)

如果在所有参数集中都有两个[ValidateScript()]参数,并且也只需要一起使用,例如:

,也可以使用Mandatory = false
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
...
}