在具有多个唯一开关的函数中使用高级参数集

在具有多个唯一开关的函数中使用高级参数集

我正在使用 Powershell 4.0。

我正在尝试编写一个 cmdlet,在这个 cmdlet 中,我想使用高级参数集来根据所选参数提供某些选项。这个特定函数本质上最终将是 Get-ADComputer,但带有针对某些选项预编程的 -SearchBase。

我总共有 6 个参数。2 个是字符串 ($ComputerName 或 $IpAddress),1 个是整数 ($OULevel) 和 3 个开关 ($ComputerOU、$AllCompany、$List)。

我为 ComputerName 和 IPAddress 分别设置了一个参数,我希望用户能够输入其中一个 - 我认为我已经弄清楚了,这很简单。但是,我希望 $OULevel、$ComputerOU 和 $AllCompany 是互斥的,这意味着如果使用其中一个,则另一个不应使用。$List 应该在每个场景中都可用。

我尝试了不同的参数设置,但都无济于事。这是我的脚本现在的样子,经过了一些修剪:

    function Get-CompanyADComputer{
         [CmdletBinding(DefaultParametersetName="ComputerName")]

    Param(
        [Parameter(Mandatory=$true,
                    ParameterSetName="ComputerName",
                    Position=0,
                    ValueFromPipeline=$false,
                    HelpMessage='Enter a computer name to search in ActiveDirectory.')]
        [Alias('Computer','CN')]
        [string]$ComputerName,

        [Parameter(Mandatory=$true,
                    ParameterSetName="IPAddress",
                    Position=0,
                    ValueFromPipeline=$false,
                    HelpMessage='Enter an IP address to search in ActiveDirectory.')]
        [Alias('IPv4Address','IPv6Address')]
        [string]$IPAddress,

        [Parameter(Mandatory=$false,
                    HelpMessage='Enter a number between 0 and 8. 0 is your current OU Container.')]
        [ValidateRange(0,8)]
        [int]$OULevel = 0,

        [Parameter()]
        [Switch]$ComputerOU,

        [Parameter()]
        [Switch]$AllCompany,

        [Parameter()]
        [Switch]$List
    )

如果您好奇,我们的 AD 是按位置、类别(计算机、用户、组、联系人等)组织的,然后在下面的每个 OU 中变得更加细化。此脚本检测您计算机的 OU 并从那里开始搜索。$OULevel 的目的是如果用户指定不同的数字,搜索将从不同的 OU 开始,然后递归搜索。$ComputerOU 的目的是让您的搜索转到默认的 Computers OU,而不是整个域或您的位置。$AllCompany 的目的是让搜索默认为整个域,而不是任何其他选择或 OU。

任何指导都值得感激。如果我的脚本不变得复杂,我似乎就无法掌握这个技巧。

答案1

我在另一个论坛上询问了 powershell 专家 Don Jones,他给了我所需的信息。他这样向我解释:

如果我理解了这个问题,那么你基本上必须考虑所有可能的组合。请记住,一个参数可以属于 1+ 个参数集。因此,你可能有一个包含 Computername 和 OULevel、Computername 和 ComputerOU 以及 Computername 和 AllCompany 的集合。这是三个。然后 IPAddress 又是这三个。我知道这并不优雅,但看看 Where-Object 的帮助——到目前为止也不优雅。列表将不属于集合,这意味着它将属于所有集合。

这让我走上了正确的道路。因此,我实际上最终改变了 cmdlet 的工作方式,因此我的答案被重新修改了,但现在我明白该怎么做了,我将更新我现有的示例,以便保持一致并希望有所帮助。

    function Get-CompanyADComputer{
     [CmdletBinding(DefaultParametersetName="ComputerName")]

Param(
    [Parameter(Mandatory=$true,
                ParameterSetName="ComputerName",
                Position=0,
                ValueFromPipeline=$false,
                HelpMessage='Enter a computer name to search in ActiveDirectory.')]
    [Parameter(Mandatory=$true,
                ParameterSetName="ComputerNameOULevel",
                Position=0,
                ValueFromPipeline=$false,
                HelpMessage='Enter a computer name to search in ActiveDirectory.')]
    [Parameter(Mandatory=$true,
                ParameterSetName="ComputerNameComputerOU",
                Position=0,
                ValueFromPipeline=$false,
                HelpMessage='Enter a computer name to search in ActiveDirectory.')]
    [Parameter(Mandatory=$true,
                ParameterSetName="ComputerNameAllCompany",
                Position=0,
                ValueFromPipeline=$false,
                HelpMessage='Enter a computer name to search in ActiveDirectory.')]
    [Alias('Computer','CN')]
    [string]$ComputerName,

    [Parameter(Mandatory=$true,
                ParameterSetName="IPAddress",
                Position=0,
                ValueFromPipeline=$false,
                HelpMessage='Enter an IP address to search in ActiveDirectory.')]
    [Parameter(Mandatory=$true,
                ParameterSetName="IPAddressOULevel",
                Position=0,
                ValueFromPipeline=$false,
                HelpMessage='Enter an IP address to search in ActiveDirectory.')]
    [Parameter(Mandatory=$true,
                ParameterSetName="IPAddressComputerOU",
                Position=0,
                ValueFromPipeline=$false,
                HelpMessage='Enter an IP address to search in ActiveDirectory.')]
    [Parameter(Mandatory=$true,
                ParameterSetName="IPAddressAllCompany",
                Position=0,
                ValueFromPipeline=$false,
                HelpMessage='Enter an IP address to search in ActiveDirectory.')]
    [Alias('IPv4Address','IPv6Address')]
    [string]$IPAddress,

    [Parameter(Mandatory=$false,
                ParameterSetName="ComputerNameOULevel",
                HelpMessage='Enter a number between 0 and 8. 0 is your current OU Container.')]
    [Parameter(Mandatory=$false,
                ParameterSetName="IPAddressOULevel",
                HelpMessage='Enter a number between 0 and 8. 0 is your current OU Container.')]
    [ValidateRange(0,8)]
    [int]$OULevel = 0,

    [Parameter(ParameterSetName="ComputerNameComputerOU")]
    [Parameter(ParameterSetName="IPAddressComputerOU")]
    [Switch]$ComputerOU,

    [Parameter(ParameterSetName="ComputerNameAllCompany")]
    [Parameter(ParameterSetName="IPAddressAllCompany")]
    [Switch]$AllCompany,

    [Parameter()]
    [Switch]$List
)

由于我不希望这 3 个参数相互使用,因此它们必须属于自己的参数集,因此当您尝试使用一个参数时,其他参数不会作为选项出现。这极大地帮助并简化了脚本编写过程本身。Powershell 参数集消除了这些选项,而不是让脚本本身考虑用户输入。

$List 参数没有参数集名称,因为我希望该参数在每个场景中都可用。

答案2

这是使用的代码动态参数新动态参数创建它们的函数:

# DotSource New-DynamicParameter function
. '.\New-DynamicParameter.ps1'

function Get-CompanyADComputer
{
    [CmdletBinding(DefaultParametersetName = 'ComputerName_AllCompany')]
    Param()
    DynamicParam
    {
        $BaseParameters = @(
            @{
                Name = 'ComputerName'
                Type = [string]
                Mandatory = $true
                ParameterSetName = 'ComputerName'
                HelpMessage = 'Enter a computer name to search in ActiveDirectory.'
                Alias = 'Computer', 'CN'
            },
            @{
                Name = 'IPAddress'
                Type = [System.Net.IPAddress]
                Mandatory = $true
                ParameterSetName = 'IPAddress'
                HelpMessage = 'Enter an IP address to search in ActiveDirectory.'
                Alias = 'IPv4Address', 'IPv6Address'
            }
        )

        $MutuallyExclusiveParameters = @(
            @{
                Name = 'OULevel'
                HelpMessage = 'Enter a number between 0 and 8. 0 is your current OU Container.'
                ValidateRange = 0, 8
                Type = [int]
            }
            @{
                Name = 'ComputerOU'
                Type = [switch]
            },
            @{
                Name = 'AllCompany'
                Type = [switch]
            }
        )

        $AllParamSetParameters = @(
            @{
                Name = 'List'
                Type = [switch]
            }
        )

        $DynamicParameters = (
            # For each base parameter
            $BaseParameters | ForEach-Object {
                # Iterate over mutually exclusive parameters
                $MutuallyExclusiveParameters | ForEach-Object -Begin {$BaseParam = $_} -Process {
                    # Generate new ParameterSet name: Base parameter ParameterSetName + mutually exclusive parameter name
                    $CurrParamSetName = '{0}_{1}' -f $BaseParam.ParameterSetName, $_.Name

                    # Clone base parameter, so we modify copy of it
                    $NewBaseParam = $BaseParam.Clone()
                    # Set its ParameterSetName
                    $NewBaseParam.ParameterSetName = $CurrParamSetName

                    # Clone mutually exclusive parameter, so we modify copy of it
                    $NewMEParam = $_.Clone()
                        # Set its ParameterSetName
                    $NewMEParam.ParameterSetName = $CurrParamSetName

                    # Output new base parameter and new mutually exclusive parameter
                    $NewBaseParam
                    $NewMEParam
                }
            }
        ) + $AllParamSetParameters # Add parameters that should exist in all parameter sets

        # Create and output new dynamic parameters
        $DynamicParameters | ForEach-Object {New-Object -TypeName psobject -Property $_} | New-DynamicParameter
    }

    Process
    {
        # Dynamic parameters don't have corresponding variables created,
        # you need to call New-DynamicParameter with CreateVariables switch to fix that.
        New-DynamicParameter -CreateVariables -BoundParameters $PSBoundParameters

        # Show all parameters
        $PSBoundParameters | Format-Table -AutoSize -HideTableHeaders | Out-String

        <#

            Your code here...

        #>
    }

}

相关内容