Настраиваемая ошибка из параметров в PowerShell
Возможно ли, чтобы ValidateScript
генерировал пользовательское сообщение об ошибке при неудачном Test-Path
теста, как, например, Test-Path
?
Вместо этого:
Test-Folder: невозможно проверить аргумент параметра "Папка". Сценарий проверки "Test -Path $ _ -Path Type Container" для аргумента со значением "blabla" не вернул результат True. Определите причину сбоя сценария проверки, а затем повторите запятую.
Было бы неплохо, чтобы он сообщал об этом вместо этого в переменной $Error
:
Папка не найдена, возможно, есть проблемы с сетью?
Код:
Function Test-Folder {
Param (
[parameter(Mandatory=$true)]
[ValidateScript({Test-Path $_ -PathType Container})]
[String]$Folder
)
Write-Host "The folder is: $Folder"
}
Обходной путь 1:
Я мог бы удалить Mandatory=$true
и изменить его, как показано ниже. Но это не дает мне правильный синтаксис Get-Help
и не выполняет Test-Path
, потому что он только проверяет Test-Path
параметра.
Function Test-Folder {
Param (
[parameter()]
[String]$Folder = $(throw "The $_ is not found, maybe there are network issues?")
)
Write-Host "The folder is: $Folder"
}
Обходной путь 2:
Я нашел этот обходной путь в сообщении в блоге, но проблема в том, что он генерирует две ошибки вместо одной.
Function Test-Folder {
Param (
[parameter(Mandatory=$true)]
[ValidateScript({
if (Test-Path $_ -PathType Container) {$true}
else {Throw "The $_ is not found, maybe there are network issues?"}})]
[String]$Folder
)
Write-Host "The folder is: $Folder"
}
Обходной путь 3:
Я также мог бы попытаться прояснить ситуацию, добавив раздел комментариев. Однако это все еще не желаемый результат, так как ошибка должна быть доступной для чтения конечным пользователям.
Function Test-Folder {
Param (
[parameter(Mandatory=$true)]
[ValidateScript({
# The folder is not found, maybe there are network issues?
Test-Path $_ -PathType Container})]
[String]$Folder
)
Write-Host "The folder is: $Folder"
}
Ответы
Ответ 1
Ваш ValidateScript
должен выглядеть примерно так:
[ValidateScript({
try {
$Folder = Get-Item $_ -ErrorAction Stop
} catch [System.Management.Automation.ItemNotFoundException] {
Throw [System.Management.Automation.ItemNotFoundException] "${_} Maybe there are network issues?"
}
if ($Folder.PSIsContainer) {
$True
} else {
Throw [System.Management.Automation.ValidationMetadataException] "The path '${_}' is not a container."
}
})]
Это даст вам сообщение, подобное этому:
Test-Folder: невозможно проверить аргумент параметра "Папка". Не удается найти путь "\\ server\Temp\asdf", так как он не существует. Может быть, есть проблемы с сетью?
Или же:
Test-Folder: невозможно проверить аргумент параметра "Папка". Путь \\server\Temp\asdf не является контейнером.
Если в старых версиях PowerShell выдается двойная ошибка, вам может потребоваться выполнить тестирование внутри функции:
Function Test-Folder {
Param (
[parameter(Mandatory=$true)]
[String]$Folder
)
try {
$Folder = Get-Item $_ -ErrorAction Stop
} catch [System.Management.Automation.ItemNotFoundException] {
Throw [System.Management.Automation.ItemNotFoundException] "The '${Folder}' is not found, maybe there are network issues?"
}
if (-not $Folder.PSIsContainer) {
Throw [System.Management.Automation.ApplicationFailedException] "The path '${_}' is not a container."
}
Write-Host "The folder is: ${Folder}"
}
Часть, которую я всегда ненавидел в PowerShell, пыталась выяснить, какую ошибку поймать; не ловя все. Так как я наконец-то понял это, вот как:
PS > Resolve-Path 'asdf'
Resolve-Path : Cannot find path '.\asdf' because it does not exist.
At line:1 char:1
+ Resolve-Path 'asdf'
+ ~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (asdf:String) [Resolve-Path], ItemNotFoundE
xception
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.ResolvePathCommand
PS > $Error[0].Exception.GetType().FullName
System.Management.Automation.ItemNotFoundException
Ответ 2
Я думаю, что вы нашли простые обходные пути.
Логика проверки параметров является расширяемой, но требует некоторого С#. Если вы реализуете абстрактный класс System.Management.Automation.ValidateArgumentsAttribute, ваша реализация может генерировать исключение System.Management.Automation.ValidationMetadtaException, которое PowerShell будет использовать для сообщения об ошибке, и вы, естественно, можете использовать любое сообщение, которое вам нравится, при создании этого исключения.
Ответ 3
Я не уверен.
Предложение: может быть, вы хотите просто перехватить ошибку и создать собственное сообщение.
trap [Error.Type] {
@"
The message you want displayed.
With maybe some additional information.
I.e.: The full message itself: {0}' -f $_.Error.Message;
continue;
}