[Из песочницы] Try/Catch/Finally

Когда вы используете Try/Catch/Finally, команда которая будет выполняться помещается в блок Try. Если произойдет ошибка в процессе выполнения команды, то она будет записана в переменную $Error, и выполнение скрипта перейдет к блоку Catch.Скрипт TestTryCatchFinally.ps1 использует команду Try в попытке создать объект. Объект создания находится в переменной $ob1. Командлет New-Object создает объект. После создания объекта и помещения его в переменную $a можно посмотреть члены объекта, используя командлет Get-Member. Следующий код иллюстрирует это: Try { «Attempting to create new object $ob1» $a = new-object $ob1 «Members of the $ob1» «New object $ob1 created» $a | Get-Member } Используйте блок Catch чтобы поймать ошибку, которая произошла в блоке Try. Вы можете указать тип ошибок для захвата, а также действие, которое бы происходило при возникновении ошибки. В скрипте TestTryCatchFinally.ps1 я слежу за ошибками типа System.Exception. Класс System.Exeption .Net Framework — это базовый класс, от которого зависят все другие исключения (exceptions). Это означает, что System.Exeption является универсальным общим классом, в сущности вы можете получить все предопределенные исключения как общие, так и системные. При перехвате ошибки вы можете указать какой код вы хотели бы выполнить. В данном примере я вывожу простую строку, которая показывает, что скрипт поймал системное исключение. Блок Catch показан ниже: Catch { [system.exception] «caught a system exception» } Блок Finally последовательности Try/Catch/Finally всегда выполняется, независимо от того произошла ошибка или нет. Это означает что какие-то вещи для завершения, которые вы хотите сделать, например для явного освобождения COM объекта, следует помещать в блок Finally. В скрипте TestTryCatchFinally.ps1 блок Finally иллюстрирует строку состояния, что скрипт завершен. Это показано далее: Finally { «end of script» } Целиком скрипт TestTryCatchFinally.ps1: TestTryCatchFinally.ps1

$ob1 = «kenobie» «Begin test»

Try { «Attempting to create new object $ob1» $a = new-object $ob1 «Members of the $ob1» «New object $ob1 created» $a | Get-Member } Catch [system.exception] { «caught a system exception» } Finally { «end of script» } Во время исполнения сценария TestTryCatchFinally.ps1 когда переменной $ob1 присваивается значение «kenobie» ошибка возникает потому что нет ни одного объекта с именем «kenobie», который можно было бы создать с помощью командлета New-Object. Следующая картинка демонстрирует вывод сценария.fca3f7c417ec49009f68ca2d593a33f9.jpg

Как видно из предыдущей картинки, строка «Begin Test» выводится потому что находится за пределами цикла Try/Catch/Finally. Внутри блока Try строка «Attempting to create new object kenobie» выводится потому что, выполняется перед командой New-Object. Это демонстрирует то, что блок Try всегда пытается выполнить код внутри него. Члены объекта «kenobie» не выводятся, также как не выводится строка «new object kenobie created». Это указывает на то, что после возникновения ошибки сценарий переходит к следующему блоку. В блоке Catch происходит захват ошибки типа System.Exeption и выводится строка «caught a system exception». Далее скрипт переходит к блоку Finally и выводит строку «end of script».

Если в сценарии переменной $ob1 будет присвоено значение «system.object» (которое является корректным значением), блок Try успешно выполнится полностью. Это видно на следующем рисунке, члены объекты выведены, и строка указывающая чтоб объект успешно создан, также выводится. Блок Catch не срабатывает, а строка «end of script» из блока Finally выводится.

8d79fd126063411885af676f5785d1a5.jpg

Вы можете использовать несколько блоков Catch в блоке Try/Catch/Finally. Нужно иметь в виду, что когда происходит исключение Windows Powershell покидает блок Try и ищет блок Catch. Будет использован первый блок Catch, который удовлетворит условиям исключения. Таким образом необходимо использовать наиболее конкретные исключения сначала, переходя к более общим.Это видно в TestTryMultipleCatchFinally.ps1.

TestTryMultipleCatchFinally.ps1

$ob1 = «foo» «Begin test» $ErrorActionPreference = «stop» Try { Get-Content foo «Attempting to create new object $ob1» $a = new-object $ob1 «Members of the $ob1» «New object $ob1 created» $a | Get-Member } Catch [System.Management.Automation.PSArgumentException] { «invalid object» } Catch [system.exception] { «caught a system exception» } Finally { «end of script» } Следующий рисунок показывает вывод сценария TestTryMultipleCatchFinally.ps1. Были сделаны два изменения: Закомментированы команды $ErrorActionPreference и Get-Content foo. Таким образом генерируемая ошибка будет возникать при попытке создать несуществующий объект. Чтобы найти конкретную ошибку, я исследовал переменную $error после запуска сценария TestTryMultipleCatchFinally.ps1. Ошибка указана в поле Exception. PS C:\> $error | fl * -F

PSMessageDetails: Exception: System.Management.Automation.PSArgumentException: Cannot find type [foo]: verify that the assembly containing this type is loaded. at System.Management.Automation.MshCommandRuntime.ThrowTerminat ingError (ErrorRecord errorRecord) TargetObject: CategoryInfo: InvalidType: (:) [New-Object], PSArgumentException FullyQualifiedErrorId: TypeNotFound, Microsoft.PowerShell.Commands.NewObjectCommand ErrorDetails: InvocationInfo: System.Management.Automation.InvocationInfo ScriptStackTrace: at , C:\Users\dyak\SkyDrive\Scripts\habrahabr\TestTry MultipleCatchFinally.ps1: line 10 PipelineIterationInfo: {} fa838a05a59a48b79d66d2536ff48460.jpg

Если скрипт имеет несколько ошибок, а значение переменной $ErroActionPreference установлено в значение «stop», первая ошибка приведет к сбою сценария. Если убрать комментарии с команд b>$ErrorActionPreference и Get-Content, первая ошибка будет поймана блоком System.Exception Catch и поэтому будет пропущено исключение аргумента. Это видно на следующем рисунке:

cb72a217610543dbab261ce543c11e90.jpg

В целом пытался перевести статью опубликованную в блоке Эда Уилсона. Надеюсь будет кому-то полезно.

© Habrahabr.ru