Когда я должен использовать Write-Error vs Throw? Ошибки завершения и неуничтожения
глядя на скрипт Get-WebFile на PoshCode:http://poshcode.org/3226 Я заметил это странное для меня приспособление:--6-->
$URL_Format_Error = [string]"..."
Write-Error $URL_Format_Error
return
в чем причина этого, в отличие от:
$URL_Format_Error = [string]"..."
Throw $URL_Format_Error
или еще лучше:
$URL_Format_Error = New-Object System.FormatException "..."
Throw $URL_Format_Error
как я понимаю, вы должны использовать Write-Error для неустранимых ошибок и Throw для завершающих ошибок, поэтому мне кажется, что вы не должны использовать Write-Error с последующим возвратом. Есть ли разница?
6 ответов
Write-Error
следует использовать, если вы хотите сообщить пользователю о некритической ошибке. По умолчанию все, что он делает, это печатает сообщение об ошибке в красном тексте на консоли. Это не останавливает конвейер или цикл от продолжения. Throw
С другой стороны производит то, что называется неустранимая ошибка. Если вы используете throw, конвейер и / или текущий цикл будут завершены. Фактически все выполнение будет прекращено, если вы не используете trap
или try/catch
структуры, отвечающей за прекращение ошибка.
есть одна вещь, чтобы отметить, если вы установите $ErrorActionPreference
to "Stop"
и использовать Write-Error
это произвести ошибку завершения.
в скрипте, с которым вы связаны, мы находим следующее:
if ($url.Contains("http")) {
$request = [System.Net.HttpWebRequest]::Create($url)
}
else {
$URL_Format_Error = [string]"Connection protocol not specified. Recommended action: Try again using protocol (for example 'http://" + $url + "') instead. Function aborting..."
Write-Error $URL_Format_Error
return
}
похоже, что автор этой функции хотел остановить выполнение этой функции и отобразить сообщение об ошибке на экране, но не хотел, чтобы весь скрипт прекратил выполнение. Автор сценария мог бы использовать throw
однако это значит, что вам придется использовать try/catch
при вызове функции.
return
выйдет из текущей области, которая может быть функцией, скриптом или блоком скрипта. Это лучше всего иллюстрируется кодом:
# A foreach loop.
foreach ( $i in (1..10) ) { Write-Host $i ; if ($i -eq 5) { return } }
# A for loop.
for ($i = 1; $i -le 10; $i++) { Write-Host $i ; if ($i -eq 5) { return } }
выход для обоих:
1
2
3
4
5
один gotcha здесь использует return
С ForEach-Object
. Это не нарушит обработку, как можно было бы ожидать.
Подробнее:
-
$ErrorActionPreference
: http://technet.microsoft.com/en-us/library/dd347731.aspx -
try/catch
: http://technet.microsoft.com/en-us/library/dd315350.aspx -
trap
: http://technet.microsoft.com/en-us/library/dd347548.aspx -
throw
: http://technet.microsoft.com/en-us/library/dd819510.aspx -
return
: http://technet.microsoft.com/en-us/library/dd347592.aspx
основное различие между Write-Error и бросить ключевое слово в PowerShell - это то, что первое просто печать текст в стандартный поток ошибок (stderr), в то время как последний на самом деле заканчивается обработка запущенной команды или функции, которая является затем обрабатывается PowerShell, отправляя информацию об ошибке на консоль.
вы можете наблюдать различное поведение двух в приведенных вами примерах:
$URL_Format_Error = [string]"..."
Write-Error $URL_Format_Error
return
в этом примере return
ключевое слово было добавлено к явно остановите выполнение сценария после отправки сообщения об ошибке на консоль. Во втором примере, с другой стороны,return
ключевое слово не требуется, так как завершение неявно выполняется throw
:
$URL_Format_Error = New-Object System.FormatException "..."
Throw $URL_Format_Error
важно: есть 2 типы завершающих ошибок, которые текущие темы справки к сожалению объединение:
сообщениизавершение ошибки, о которых сообщают командлеты в определенных ситуациях, не поддающихся восстановлению, и выражения, в которых возникает ошибка выполнения .NET exception / A PS; только сообщении прекращается, и выполнение скрипта продолжается по умолчанию.
скриптзавершение ошибки, как спровоцированный
Throw
или путем эскалации одного из других типов ошибок через предпочтение действия ошибки-переменная / значение параметраStop
.
Если не пойман, они завершают текущий поток выполнения (т. е. не только текущий скрипт, но и все его вызывающие объекты, если это применимо).
для a полный обзор обработки ошибок PowerShell см. В разделе эта проблема с документацией GitHub.
остальная часть этого поста фокусируется на непрерывающую и заявление-оконечный ошибки.
чтобы дополнить существующие полезные ответы с акцентом на ядро вопроса:как вы выбрать сообщить ли заявление -завершение или непрерывающую?
Отчеты Об Ошибках Командлета содержит полезные рекомендации; позвольте мне попытаться прагматичный резюме:
общая идея непрерывающую ошибки должны позволять "отказоустойчивую" обработку больших входных наборов: неспособность обработать подмножество входных объектов не должна (по умолчанию) прерывать-потенциально длительный-процесс в целом, позволяя вы должны проверить ошибки и обработать только ошибка объектов - как сообщается через записи об ошибках, собранные в автоматической переменной $Error
.
-
отчет НЕПРЕРЫВАЮЩУЮ ошибка, если ваш командлет / расширенная функция:
- принимает несколько входных объектов, через входной сигнал трубопровода и / или массив-значные параметры, и
- ошибок для Конкретные объекты ввода и
-
эти ошибки не препятствуют дальнейшей обработке входных объектов в принципе (ситуативно, возможно, не осталось объектов ввода и / или предыдущие объекты ввода, возможно, уже были успешно обработаны).
- в расширенных функциях используйте
$PSCmdlet.WriteError()
сообщить о неустранимой ошибке (Write-Error
, к сожалению, не вызывает$?
значение$False
на абонента объем - вижу этот выпуск GitHub). -
обращение неустранимая ошибка:
$?
сообщает вам, сообщила Ли самая последняя команда по крайней мере один неустранимая ошибка.- таким образом,
$?
будучи$False
может означать, что любое (непустое) подмножество ввода объектов, не были должным образом обработаны, возможно, весь набор. - предпочтения переменной
$ErrorActionPreference
и/или общий параметр командлета-ErrorAction
может изменять поведение неперерывных ошибок (только) с точки зрения поведения вывода ошибок и того, должны ли неперерывные ошибки быть увеличены до скрипт-прекращение близких.
- таким образом,
- в расширенных функциях используйте
-
отчет ЗАЯВЛЕНИЕ-ОКОНЧАНИЕ ошибка все остальные случаи.
- в частности, при возникновении ошибки в командлете / расширенной функции, которая принимает только один или нет входной объект и выводит нет или один выходной объект.
- в расширенных функциях вы должны использовать
$PSCmdlet.ThrowTerminatingError()
для генерации ошибки завершения оператора. - обратите внимание, что, напротив,
Throw
ключевое слово генерирует скрипт-устранимая ошибка, которая прерывает весь скрипт. -
обращение ошибка завершения инструкции: a
try/catch
обработчик илиtrap
оператор может быть использован (который не может использоваться с непрерывающую ошибки), но обратите внимание, что даже сообщении-завершение ошибок по умолчанию не препятствует запуску остальной части скрипта. Как с непрерывающую ошибки$?
отражает$False
если предыдущий оператор вызвал ошибку завершения оператора.
- в расширенных функциях вы должны использовать
- в частности, при возникновении ошибки в командлете / расширенной функции, которая принимает только один или нет входной объект и выводит нет или один выходной объект.
к сожалению, не все собственные командлеты PowerShell играйте по этим правилам:
хотя вряд ли,
New-TemporaryFile
(PSv5+) сообщит о неустранимой ошибке, если она не удалась, несмотря на то, что не принимает вход трубопровода и только производит один выходной объект-это, вероятно, изменится в v6, однако: см. эта проблема GitHub.Resume-Job
в справке утверждается, что передача неподдерживаемого типа задания (например, задания, созданного с помощьюStart-Job
, который не поддерживается, потому чтоResume-Job
относится только к процесс jobs) вызывает ошибку завершения, но это не так, как в PSv5.1.
Write-Error
позволяет потребителю функции подавлять сообщение об ошибке с помощью -ErrorAction SilentlyContinue
(или -ea 0
). В то время как throw
требует try{...} catch {..}
использовать попробовать...поймать с Write-Error
:
try {
SomeFunction -ErrorAction Stop
}
catch {
DoSomething
}
кроме ответ Энди Арисменди:
ли Пишут-Ошибка завершает процесс или не зависит от $ErrorActionPreference
настройка.
для нетривиальных скриптов, $ErrorActionPreference = "Stop"
это рекомендуемое значение чтобы потерпеть неудачу быстро.
" поведение PowerShell по умолчанию в отношении ошибок, которое заключается в продолжайте по ошибке ...чувствует себя очень VB6 " по ошибке резюме Следующий" - иш"
(от http://codebetter.com/jameskovacs/2010/02/25/the-exec-problem/)
однако, это делает Write-Error
вызывает прерывание.
использовать Пишут-Ошибка в качестве команды, не заканчивающейся независимо от других параметров среды, вы можете использовать общий параметр -ErrorAction
со значением Continue
:
Write-Error "Error Message" -ErrorAction:Continue
Если ваше чтение кода правильно, то вы правы. Завершающие ошибки должны использовать throw
, и если вы имеете дело с типами .NET, то полезно также следовать соглашениям об исключениях .NET.