如何更改参数的抛出消息?
How do you change a parameter's throw message?
问题:
希望更改显示的错误消息以说明他们需要将“-passed、-warning 或-failed”包含在 cmdlet 参数中,或者不关心这三个是否丢失并编写消息(假设它在那里) .
说明:
创建了一个接受三个参数的函数:消息、第二条消息和消息状态(通过,
失败,警告)。我收到默认错误消息“无法使用指定的命名解析参数
参数。”无论您是否通过以下方式传递消息,都会发生这种情况:
PS C:\> Write-Message;
Write-Message : Parameter set cannot be resolved using the specified named parameters.
...
//or
PS C:\> Write-Message -Message "Hello World";
但是,如果您输入 'status' 参数,它将毫无问题地工作:
PS C:\> Write-Message -Message "Hello World" -Passed;
Hello World
('Hello World' 应该是这里的绿色,但 Stack Overflow 还没有那个特性)
有问题的函数:
Function Write-Message {
param(
[string]$Message,
[string]$MessageTwo,
[Parameter(Mandatory=$false, ValueFromPipelineByPropertyName = $true, ParameterSetName ="Passed")][switch]$Passed,
[Parameter(Mandatory=$false, ValueFromPipelineByPropertyName = $true, ParameterSetName ="Warning")][switch]$Warning,
[Parameter(Mandatory=$false, ValueFromPipelineByPropertyName = $true, ParameterSetName ="Failed")][switch]$Failed
);
$NewLineNeeded = [string]::IsNullOrEmpty($MessageTwo);
if ($Passed){
$color = 'green';
}
if($Warning){
$color = 'yellow';
}
if($Failed){
$color = 'red';
}
if($Passed -or $Warning -or $Failed){
if(!$NewLineNeeded){
Write-Host $MessageOne -NoNewline;
Write-Host $MessageTwo -ForegroundColor $color;
} else {
Write-Host $Message -ForegroundColor $color;
}
}
}
添加一个 "default" 参数集来解决这个问题。您实际上不必在代码中使用参数集,因此即使使用 "Default" 之类的东西也可以在不对代码进行额外更改的情况下使用。在编写更复杂的 cmdlet 时,我自己 运行 在其中使用参数集作为互斥参数,但有些参数与参数集无关。
Function Write-Message {
[CmdletBinding(DefaultParameterSetName="Default")]
Param(
...
当您只使用没有参数集的参数时,Powershell 似乎对正在使用哪个参数集感到困惑,并且您还在 cmdlet 中定义了参数集。
您只需满足以下所有条件即可:
- 已明确定义两个或更多参数集
- 尚未将现有参数集之一绑定为默认值
- 具有(并调用您的例程)未绑定到任一集合的参数
如 中所述,连同发生的一些幕后信息,这可能是某种错误,此解决方案是解决方法。
用更多背景信息补充 :
未通过其 [Parameter()]
属性标记为至少属于一个参数集的参数:
被隐含地视为 所有 定义参数集的一部分。
分配了自动 __AllParameterSets
参数集。
您可以使用 Write-Message
函数验证如下:
(Get-Command Write-Message).Parameters.GetEnumerator() |
Select-Object @{ n='ParameterName'; e = { $_.Key } },
@{ n='ParameterSets'; e = { $_.Value.ParameterSets.GetEnumerator().ForEach('Key') } }
以上结果(常用参数省略):
ParameterName ParameterSets
------------- -------------
Message __AllParameterSets
MessageTwo __AllParameterSets
Passed Passed
Warning Warning
Failed Failed
# ...
重要:一旦您将参数标记为属于参数集,它仅属于该参数集,如果它也需要属于其他人,你需要多个,单独的[Parameter(ParameterSetName = '...')]
属性——每个感兴趣的参数集一个。
当使用一组给定的参数值调用给定的函数或脚本时,PowerShell 会尝试明确地推断要应用的参数集并报告 selected 参数集 $PSCmdlet.ParameterSetName
.
如果无法明确推断单个参数集,则会发生语句终止错误;也就是说,函数的调用根本失败了(但默认情况下脚本的执行会继续)。
发生这种情况的原因有两个:
传递了互斥参数:指定了属于不同参数集的参数(没有至少一个共同的关联参数集的参数)。
传递了一个不明确的参数组合:不清楚select 设置的参数是什么,因为可以应用多个参数。
两种情况下的错误信息是一样的:
Parameter set cannot be resolved using the specified named parameters. One or more parameters issued cannot be used together or an insufficient number of parameters were provided.
顺便说一句:如果您仅指定参数名称的 prefix(PowerShell 通常支持),并且该前缀不明确,即匹配 多个参数;例如,-Out
是不明确的,因为它同时匹配 -OutVariable
和 -OutBuffer
:
Parameter cannot be processed because the parameter name 'Out' is ambiguous. Possible matches include: -OutVariable -OutBuffer.
如果指定无参数或仅指定未明确标记为属于参数集的参数and 您还没有定义 default 参数集,PowerShell selects __AllParameterSets
集并反映在 $PSCmdlet.ParameterSetName
.
然而,令人惊讶的是,只有 one 明确定义的参数集才有效。
有两个或多个显式参数集 - 如您的情况 - PowerShell 认为这种情况不明确并报告错误。
这种令人惊讶的行为在 this GitHub issue 中进行了讨论。
解决方法,如 Bender 的回答所示,是定义一个默认参数集 通过放置在 param(...)
块上方的 [CmdletBinding()]
属性;例如:[CmdletBinding(DefaultParameterSetName='Default')]
这个参数集是隐式创建的,名称可以自由选择;没有任何实际参数必须被标记为属于它。
现在,当您不指定任何参数或仅指定那些没有显式参数集标记的参数时,调用会成功,并且 $PSCmdlet.ParameterSetName
反映默认参数集的名称。
问题: 希望更改显示的错误消息以说明他们需要将“-passed、-warning 或-failed”包含在 cmdlet 参数中,或者不关心这三个是否丢失并编写消息(假设它在那里) .
说明: 创建了一个接受三个参数的函数:消息、第二条消息和消息状态(通过, 失败,警告)。我收到默认错误消息“无法使用指定的命名解析参数 参数。”无论您是否通过以下方式传递消息,都会发生这种情况:
PS C:\> Write-Message;
Write-Message : Parameter set cannot be resolved using the specified named parameters.
...
//or
PS C:\> Write-Message -Message "Hello World";
但是,如果您输入 'status' 参数,它将毫无问题地工作:
PS C:\> Write-Message -Message "Hello World" -Passed;
Hello World
('Hello World' 应该是这里的绿色,但 Stack Overflow 还没有那个特性)
有问题的函数:
Function Write-Message {
param(
[string]$Message,
[string]$MessageTwo,
[Parameter(Mandatory=$false, ValueFromPipelineByPropertyName = $true, ParameterSetName ="Passed")][switch]$Passed,
[Parameter(Mandatory=$false, ValueFromPipelineByPropertyName = $true, ParameterSetName ="Warning")][switch]$Warning,
[Parameter(Mandatory=$false, ValueFromPipelineByPropertyName = $true, ParameterSetName ="Failed")][switch]$Failed
);
$NewLineNeeded = [string]::IsNullOrEmpty($MessageTwo);
if ($Passed){
$color = 'green';
}
if($Warning){
$color = 'yellow';
}
if($Failed){
$color = 'red';
}
if($Passed -or $Warning -or $Failed){
if(!$NewLineNeeded){
Write-Host $MessageOne -NoNewline;
Write-Host $MessageTwo -ForegroundColor $color;
} else {
Write-Host $Message -ForegroundColor $color;
}
}
}
添加一个 "default" 参数集来解决这个问题。您实际上不必在代码中使用参数集,因此即使使用 "Default" 之类的东西也可以在不对代码进行额外更改的情况下使用。在编写更复杂的 cmdlet 时,我自己 运行 在其中使用参数集作为互斥参数,但有些参数与参数集无关。
Function Write-Message {
[CmdletBinding(DefaultParameterSetName="Default")]
Param(
...
当您只使用没有参数集的参数时,Powershell 似乎对正在使用哪个参数集感到困惑,并且您还在 cmdlet 中定义了参数集。
您只需满足以下所有条件即可:
- 已明确定义两个或更多参数集
- 尚未将现有参数集之一绑定为默认值
- 具有(并调用您的例程)未绑定到任一集合的参数
如
用更多背景信息补充
未通过其 [Parameter()]
属性标记为至少属于一个参数集的参数:
被隐含地视为 所有 定义参数集的一部分。
分配了自动
__AllParameterSets
参数集。
您可以使用 Write-Message
函数验证如下:
(Get-Command Write-Message).Parameters.GetEnumerator() |
Select-Object @{ n='ParameterName'; e = { $_.Key } },
@{ n='ParameterSets'; e = { $_.Value.ParameterSets.GetEnumerator().ForEach('Key') } }
以上结果(常用参数省略):
ParameterName ParameterSets
------------- -------------
Message __AllParameterSets
MessageTwo __AllParameterSets
Passed Passed
Warning Warning
Failed Failed
# ...
重要:一旦您将参数标记为属于参数集,它仅属于该参数集,如果它也需要属于其他人,你需要多个,单独的[Parameter(ParameterSetName = '...')]
属性——每个感兴趣的参数集一个。
当使用一组给定的参数值调用给定的函数或脚本时,PowerShell 会尝试明确地推断要应用的参数集并报告 selected 参数集 $PSCmdlet.ParameterSetName
.
如果无法明确推断单个参数集,则会发生语句终止错误;也就是说,函数的调用根本失败了(但默认情况下脚本的执行会继续)。 发生这种情况的原因有两个:
传递了互斥参数:指定了属于不同参数集的参数(没有至少一个共同的关联参数集的参数)。
传递了一个不明确的参数组合:不清楚select 设置的参数是什么,因为可以应用多个参数。
两种情况下的错误信息是一样的:
Parameter set cannot be resolved using the specified named parameters. One or more parameters issued cannot be used together or an insufficient number of parameters were provided.
顺便说一句:如果您仅指定参数名称的 prefix(PowerShell 通常支持),并且该前缀不明确,即匹配 多个参数;例如,-Out
是不明确的,因为它同时匹配 -OutVariable
和 -OutBuffer
:
Parameter cannot be processed because the parameter name 'Out' is ambiguous. Possible matches include: -OutVariable -OutBuffer.
如果指定无参数或仅指定未明确标记为属于参数集的参数and 您还没有定义 default 参数集,PowerShell selects __AllParameterSets
集并反映在 $PSCmdlet.ParameterSetName
.
然而,令人惊讶的是,只有 one 明确定义的参数集才有效。
有两个或多个显式参数集 - 如您的情况 - PowerShell 认为这种情况不明确并报告错误。
这种令人惊讶的行为在 this GitHub issue 中进行了讨论。
解决方法,如 Bender 的回答所示,是定义一个默认参数集 通过放置在 param(...)
块上方的 [CmdletBinding()]
属性;例如:[CmdletBinding(DefaultParameterSetName='Default')]
这个参数集是隐式创建的,名称可以自由选择;没有任何实际参数必须被标记为属于它。
现在,当您不指定任何参数或仅指定那些没有显式参数集标记的参数时,调用会成功,并且 $PSCmdlet.ParameterSetName
反映默认参数集的名称。