Когда я должен использовать 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