Как изменить сообщение о выбросе параметра?

Вопрос: Хотите либо изменить отображаемое сообщение об ошибке, чтобы указать, что им нужно включить в параметры командлета параметр -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" здесь должен быть зеленого цвета, но stackru еще не имеет этой функции)

Рассматриваемая функция:

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 ответа

Решение

Для решения этой проблемы добавьте набор параметров "по умолчанию". На самом деле вам не обязательно использовать набор параметров в вашем коде, поэтому даже использование чего-то вроде "Default" будет работать без дополнительных изменений в вашем коде. Я сам сталкивался с этим при написании более сложных командлетов, где я использую наборы параметров для взаимоисключающих параметров, но некоторые параметры не зависят от набора параметров.

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

Кажется, что Powershell не понимает, какой набор параметров используется, когда вы используете только параметры без набора параметров, и вы также определили наборы параметров в своем командлете.

Вам нужно только сделать это, все следующие условия выполняются:

  • Явно определили два или более набора параметров
  • Еще не связали один из ваших существующих наборов параметров по умолчанию
  • Иметь (и вызывать свою процедуру с) аргументами, которые не связаны ни с одним из

Как объясняется в ответе mklement0, наряду с некоторой внутренней информацией о том, что происходит, это, возможно, своего рода ошибка, и это решение является обходным путем.

Чтобы дополнить эффективное решение Бендера Величайшего и полезное объяснение дополнительной справочной информацией:

Параметры, которые не помечены как принадлежащие хотя бы к одному набору параметров, через их [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.

Если один набор параметров не может быть определен однозначно, возникает ошибка завершения оператора; то есть вызов функции принципиально не выполняется (но выполнение сценария продолжается по умолчанию). Это может произойти по одной из двух причин:

  • Были переданы взаимоисключающие параметры: были указаны параметры, принадлежащие к разным наборам параметров (параметры, у которых нет хотя бы одного общего набора связанных параметров).

  • Была передана неоднозначная комбинация параметров: неясно, какой набор параметров выбрать, поскольку может применяться несколько параметров.

Сообщение об ошибке одинаково в обоих случаях:

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), и этот префикс является неоднозначным, т. Е. Соответствует нескольким параметрам; например,-Out неоднозначно, потому что соответствует обоим -OutVariable а также -OutBuffer:

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

Если вы не указываете никаких параметров или указываете только те параметры, которые явно не помечены как принадлежащие к набору параметров, и вы не определили набор параметров по умолчанию, PowerShell выберет__AllParameterSets установить и отражает это в $PSCmdlet.ParameterSetName.
Однако, как ни странно, это работает, только если есть только один явно определенный набор параметров.

С двумя или более явными наборами параметров - как в вашем случае - PowerShell считает этот случай неоднозначным и сообщает об ошибке.

Это удивительное поведение обсуждается в этом выпуске GitHub.

Обходной путь, как показано в ответ Бендера, чтобы определить по умолчанию набор параметров с помощью[CmdletBinding()] атрибут размещен над param(...)блок; например:[CmdletBinding(DefaultParameterSetName='Default')]

Этот набор параметров создается неявно, и его имя можно выбрать произвольно; никакие фактические параметры не могут быть помечены как принадлежащие ему.

Теперь, когда вы не указываете параметры или только те, без явной маркировки набора параметров, вызов завершается успешно и $PSCmdlet.ParameterSetName отражает имя набора параметров по умолчанию.

Другие вопросы по тегам