我有一个带动态参数和常规参数的函数。
动态参数名为Role
,常规参数名为RolePattern
。
它们是不同集合的一部分。默认设置是使用动态参数。
如果我尝试使用带动态参数的集合,Powershell认为我使用了常规参数。
如果我将常规参数的名称更改为不以Role
开头的内容,则可以正常工作。我做错了什么?
以下是测试脚本:
function Test-ParameterConflict {
[CmdletBinding(DefaultParameterSetName = 'Dynamic')]
[OutputType()]
Param (
[Parameter(Mandatory = $false, ParameterSetName = 'Pattern')]
[ValidateNotNullOrEmpty()]
[string] $RolePattern
)
dynamicParam {
# Create the dictionary
$runtimeParameterDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary
# Set the dynamic parameter's name
$parameterName = 'Role'
# Create and set the parameter's attributes
$parameterAttribute = New-Object System.Management.Automation.ParameterAttribute
$parameterAttribute.Mandatory = $true
$parameterAttribute.ValueFromPipeline = $true
$parameterAttribute.ValueFromPipelineByPropertyName = $true
$parameterAttribute.ParameterSetName = 'Dynamic'
# Create the collection of attributes
$attributeCollection = New-Object System.Collections.ObjectModel.Collection[System.Attribute]
# Add the attributes to the attributes collection
$attributeCollection.Add($parameterAttribute)
# Generate and set the ValidateSet
$validValues = @('Role1', 'Role2', 'Role3')
$validateSetAttribute = New-Object System.Management.Automation.ValidateSetAttribute($validValues)
# Add the ValidateSet to the attributes collection
$attributeCollection.Add($validateSetAttribute)
# Create and add the dynamic parameter to the dictionary
$runtimeParameter = New-Object System.Management.Automation.RuntimeDefinedParameter($parameterName, [string[]], $attributeCollection)
$runtimeParameterDictionary.Add($parameterName, $runtimeParameter)
return $runtimeParameterDictionary
}
Process {
"ParameterSetName = $($PSCmdlet.ParameterSetName)"
$PSCmdlet.MyInvocation.BoundParameters
}
}
基本上语法是:
Test-ParameterConflict [-RolePattern <string>]
Test-ParameterConflict -Role <string[]>
这是输出:
Test-ParameterConflict -Role Role1 | ft -AutoSize
ParameterSetName = Pattern
Key Value
--- -----
RolePattern Role1
答案 0 :(得分:1)
这听起来像是PowerShell的一个问题。它不像处理常规参数那样处理动态参数 - 无论是错误还是设计。
如果我将常规参数的名称更改为不以“角色”开头的内容,则可以正常使用
这部分很重要,并解释了您遇到此问题的原因。 PowerShell会尽可能自动完成参数,如果参数名称不明确,则返回错误。
例如:
PS C:\> Get-help Test -f
Get-Help : Parameter cannot be processed because the parameter name 'f' is ambiguous. Possible matches
include: -Functionality -Full.
在脚本中,使用-R
会导致类似的错误,因为脚本无法告诉我们我们指的是-Role
或RolePattern
。相反,我们得到:
PS C:\> Test-ParameterConflict -R "1"
ParameterSetName = Pattern
Key Value
--- -----
RolePattern 1
因此,脚本自动完成从-Role
到-RolePattern
的参数名称。即使标签完整,语法也不然。显然,常规参数的优先级高于动态参数,因此匹配两者的任何内容都将被视为-RolePattern
一种解决方法是使用不同的名称,如原始帖子中所述。另一个是将两个参数都设置为动态或常规。
E.g。将两个参数都设置为动态:
function Test-ParameterConflict {
[CmdletBinding(DefaultParameterSetName = 'Dynamic')]
[OutputType()]
Param (
)
dynamicParam {
# Create the dictionary
$runtimeParameterDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary
# Set the dynamic parameter's name
$parameterName = 'Role'
# Create and set the parameter's attributes
$parameterAttribute = New-Object System.Management.Automation.ParameterAttribute
$parameterAttribute.Mandatory = $true
$parameterAttribute.ValueFromPipeline = $true
$parameterAttribute.ValueFromPipelineByPropertyName = $true
$parameterAttribute.ParameterSetName = 'Dynamic'
# Create the collection of attributes
$attributeCollection = New-Object System.Collections.ObjectModel.Collection[System.Attribute]
# Add the attributes to the attributes collection
$attributeCollection.Add($parameterAttribute)
# Generate and set the ValidateSet
$validValues = @('Role1', 'Role2', 'Role3')
$validateSetAttribute = New-Object System.Management.Automation.ValidateSetAttribute($validValues)
# Add the ValidateSet to the attributes collection
$attributeCollection.Add($validateSetAttribute)
# Create and add the dynamic parameter to the dictionary
$runtimeParameter = New-Object System.Management.Automation.RuntimeDefinedParameter($parameterName, [string[]], $attributeCollection)
$runtimeParameterDictionary.Add($parameterName, $runtimeParameter)
#===============================================================================
# Copied from above, with different $parameterName and $validValues
$parameterName = 'RolePattern'
$parameterAttribute = New-Object System.Management.Automation.ParameterAttribute
$parameterAttribute.Mandatory = $true
$parameterAttribute.ValueFromPipeline = $true
$parameterAttribute.ValueFromPipelineByPropertyName = $true
$parameterAttribute.ParameterSetName = 'Pattern'
$attributeCollection = New-Object System.Collections.ObjectModel.Collection[System.Attribute]
$attributeCollection.Add($parameterAttribute)
$validValues = @('Role4', 'Role5', 'Role6')
$validateSetAttribute = New-Object System.Management.Automation.ValidateSetAttribute($validValues)
$attributeCollection.Add($validateSetAttribute)
$runtimeParameter = New-Object System.Management.Automation.RuntimeDefinedParameter($parameterName, [string[]], $attributeCollection)
$runtimeParameterDictionary.Add($parameterName, $runtimeParameter)
#===============================================================================
return $runtimeParameterDictionary
}
Process {
"ParameterSetName = $($PSCmdlet.ParameterSetName)"
$PSCmdlet.MyInvocation.BoundParameters
}
}