我正在使用 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...
#>
}
}