【问题标题】:Multiple parameter sets and PowerShell多个参数集和 PowerShell
【发布时间】:2015-07-24 00:54:39
【问题描述】:

我正在构建一个具有三个不同参数集的函数,其中两个参数集与第三个参数集重叠。选项如下所示:

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

为了更清楚一点,这里是功能的部分完成版本:

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

该功能的目的是自动化将 AD 帐户转出到公司内其他位置的过程。 RetainGroups 会在设置时自动保留用户组,RemoveFromAllGroups 会自动从他们的组中删除用户。两个开关不能一起使用。此外,如果设置了TransferHomeDrive,它将调用一个函数来使用内部工具安排传输。

换句话说,RetainGroupsRemoveFromAllGroups 应该是所有参数集的成员(类似于Username),但不能一起使用。

我尝试了两种方法。第一个:

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

使用这种技术,retain 和 remove 不能一起使用,但 OldServerNewServer 不再是强制性的。如果我将它们更改为:

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

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

它们将是强制性的,但它不再关心是否设置了TransferHomeDrive

如果我以相反的方式设置:

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

那么OldServerNewServer 将是强制性的,但RetainGroupsRemoveFromAllGroups 可以一起使用。此外,如果我同时使用 retain 和 remove,那么 OldServerNewServer 将成为强制性的,但单独使用时则不会。

我该如何进行这项工作?

【问题讨论】:

  • 我目前正在解析所有这些,但真正有助于使用参数集的是在您的函数上使用 Get-Help 以向您展示 PowerShell 如何解释您的参数集。如果您可以为您尝试过的每个配置执行此操作,然后将输出编辑到您的答案中,那将非常有帮助。
  • 好问题,谢谢!

标签: powershell


【解决方案1】:

好的,我想我明白了。您想要的可能组合是:

  1. -RetainGroups
  2. -RemoveFromAllGroups
  3. -RetainGroups 加上-TransferHomeDrive
  4. -RemoveFromAllGroups 加上-TransferHomeDrive
  5. 仅限-UserName
  6. -UserName-TransferHomeDrive

我假设-OldServer-NewServer 仅在移动主驱动器时适用,因此无论何时移动主驱动器,它们都是强制性的。如果不是这样,请告诉我。

所以你这里有 6 个参数集。与 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
)

}

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

简化它

如果您想让它不那么令人生畏,您可以考虑将删除和保留开关合并到一个参数中,如下所示:

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

我确实想指出,虽然 定义 更简单,但这并不意味着它更好。您可能希望优化 caller 的参数集,如果这是您计划在 shell 中以交互方式大量使用的函数,而不是从其他脚本调用(和看起来可能是这种情况)。

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

【讨论】:

  • 好吧,现在我看起来不傻,你写的答案和我差不多(加上更多)几乎比我早 45 分钟。希望我在提交答案之前看到这个。
  • 嗯,这在我们所有人的某个时刻都会发生,@TheMadTechnician。 :)
  • 这是我在网上看到的对 PowerShell 参数集最好的解释。这个答案比标准的 MSDN 页面要好得多。
  • 感谢@RossPatterson!
【解决方案2】:

通过添加另外两个参数集,您可以做您想做的事。这是必需的,因为您现在有 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
    )
}

【讨论】:

    【解决方案3】:

    你也可以使用[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
    ...
    }
    

    【讨论】:

      猜你喜欢
      • 2021-09-13
      • 2022-11-26
      • 2016-11-25
      • 2015-07-06
      • 2017-06-05
      • 2021-06-27
      • 1970-01-01
      • 1970-01-01
      • 2010-10-12
      相关资源
      最近更新 更多