Как изменить сообщение о выбросе параметра?
Вопрос: Хотите либо изменить отображаемое сообщение об ошибке, чтобы указать, что им нужно включить в параметры командлета параметр -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
отражает имя набора параметров по умолчанию.