Когда я должен использовать Write-Error vs Throw? Завершающие и не завершающие ошибки
глядя на скрипт Get-WebFile на PoshCode:http://poshcode.org/3226 Я заметил это странное для меня приспособление:
$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 для непрекращающихся ошибок и бросать для прерывания ошибок, поэтому мне кажется, что вы не должны использовать Write-Error с последующим возвратом. Есть ли разница?
6 ответов:
Write-Errorследует использовать, если вы хотите сообщить пользователю о некритической ошибке. По умолчанию все, что он делает, это печатает сообщение об ошибке в красном тексте на консоли. Это не останавливает конвейер или цикл от продолжения.ThrowС другой стороны производит то, что называется неустранимая ошибка. Если вы используете throw, конвейер и / или текущий цикл будут завершены. Фактически все выполнение будет прекращено, если вы не используетеtrapилиtry/catchструктура для того чтобы отрегулировать прекращать ошибка.есть одна вещь, чтобы отметить, если вы установите
$ErrorActionPreferenceдо"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один попался здесь, используя
returnСForEach-Object. Он не будет нарушать обработку, как можно было бы ожидать.Подробнее:
$ErrorActionPreference: http://technet.microsoft.com/en-us/library/dd347731.aspxtry/catch: http://technet.microsoft.com/en-us/library/dd315350.aspxtrap: http://technet.microsoft.com/en-us/library/dd347548.aspxthrow: http://technet.microsoft.com/en-us/library/dd819510.aspxreturn: 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или путем эскалации одного из других типов ошибок с помощью параметра error-action preference-variable / parameter valueStop.
Если они не пойманы, они завершают текущий поток выполнения (т. е. не только текущий скрипт, но и все его вызывающие объекты, если это применимо).для 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 }
кроме ответ Энди Арисменди:
ли Write-Error завершает процесс или нет, зависит от
$ErrorActionPreferenceнастройка.для нетривиальных скриптов,
$ErrorActionPreference = "Stop"это рекомендуемое значение чтобы потерпеть неудачу быстро." поведение PowerShell по умолчанию в отношении ошибок, которое заключается в следующем продолжайте по ошибке ...чувствует себя очень VB6 " на ошибку резюме Далее" - иш"
(от http://codebetter.com/jameskovacs/2010/02/25/the-exec-problem/)
однако, это делает
Write-Errorвызывает прерывание.использовать Write-Error в качестве команды без завершения независимо от других параметров среды, вы можете использовать общий параметр
-ErrorActionсо значениемContinue:Write-Error "Error Message" -ErrorAction:Continue