如何更改参数的抛出消息?

时间:2019-11-12 15:51:34

标签: powershell parameter-sets

问题: 试图更改显示的错误消息,说他们需要cmdlet参数包含“ -passed,-warning或-failed”,或者不关心这三个消息是否丢失并写消息(假定在此处) 。

说明: 创建了一个函数,该函数接受三个参数:消息,第二消息和消息状态(通过, 失败,警告)。我收到默认错误消息“无法使用指定的名称解析参数 参数。”无论您是否通过以下方式传递消息,都会发生这种情况:

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

2 个答案:

答案 0 :(得分:3)

添加一个“默认”参数集来解决此问题。实际上,您不必使用代码中的参数集,因此即使使用“默认”之类的代码也无需更改代码即可使用。在编写更复杂的cmdlet时遇到了这种麻烦,我在其中将参数集用于互斥参数,但是某些参数与参数集无关。

Function Write-Message {
  [CmdletBinding(DefaultParameterSetName="Default")]
  Param(
...

当仅使用不带参数集的参数,并且在cmdlet中也定义了参数集时,Powershell似乎对正在使用哪个参数集感到困惑。

您只需要满足以下所有条件,即可:

  • 已明确定义两个或更多参数集
  • 尚未将现有参数集之一绑定为默认值
  • 具有未绑定到任一集合的参数(并使用其调用例程)

mklement0's answer中所述,以及有关发生的情况的一些幕后信息,这可能是一种错误,并且此解决方案是解决方法。

答案 1 :(得分:3)

Bender the Greatest' effective solution and helpful explanation补充更多的背景信息

未通过其[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会尝试明确推断要应用的参数集,并报告$PSCmdlet.ParameterSetName 中的选定参数集。 / p>

如果不能明确地推断单个参数集,则会发生语句终止错误;也就是说,从根本上来说该函数的调用会失败(但是默认情况下会继续执行脚本)。 发生这种情况有两个原因之一:

    传递了
  • 相互排斥的参数:指定了属于不同参数集的参数(没有至少一个相关参数集相同的参数)。

  • 传递了一个模糊的参数组合:尚不清楚要选择哪个参数集,因为可以应用多个参数。

在两种情况下,错误消息都是相同的:

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.

顺便说一句:如果仅指定参数名称的前缀(PowerShell通常支持),并且前缀不明确,即与 multiple 参数;例如-Out含糊不清,因为它与-OutVariable-OutBuffer都匹配:

Parameter cannot be processed because the parameter name 'Out' is ambiguous. Possible matches include: -OutVariable -OutBuffer.

如果您指定 no 参数或仅指定未明确标记为属于参数集的参数,则尚未定义默认参数集,PowerShell将选择__AllParameterSets集并将其反映在$PSCmdlet.ParameterSetName中。
但是,令人惊讶的是,只有在只有一个明确定义的参数集的情况下,这才起作用。

具有两个或多个显式参数集-如您的情况-PowerShell认为这种情况不明确并报告错误。

this GitHub issue中讨论了这种令人惊讶的行为。

如Bender的答案所示,解决方法是通过上方的[CmdletBinding()]属性来定义一个默认参数设置param(...)块;例如: [CmdletBinding(DefaultParameterSetName='Default')]

此参数集是隐式创建的,可以自由选择其名称;无需将实际参数标记为属于它。

现在,当您不指定参数或仅指定没有显式参数集标记的参数时,调用成功,并且$PSCmdlet.ParameterSetName反映默认参数集的名称。