Вы когда-нибудь запускали сценарий или командлет PowerShell и сталкивались с оглушительной стеной текста – красного цвета – подобной показанной ниже?

Ошибки могут стать подавляющими и запутанными. И, прежде всего, ошибки часто сложно читать, что делает определение того, что и где пошло не так в сценарии, почти невозможным.
К счастью, у вас есть несколько вариантов в PowerShell, чтобы улучшить ситуацию с помощью обработки ошибок. Используя обработку ошибок, ошибки можно фильтровать и отображать таким образом, что их легче понимать. Понимание ошибки делает добавление дополнительной логики к обработке ошибок легким.
В этой статье вы узнаете ошибках в PowerShell и о том, как их можно перехватывать для выполнения обработки ошибок с использованием блоков Try Catch
PowerShell (а также блоков finally
).
Понимание того, как работают ошибки в PowerShell
Прежде чем погружаться в обработку ошибок, давайте сначала рассмотрим несколько концепций вокруг ошибок в PowerShell. Понимание ошибок может привести к лучшим стратегиям обработки ошибок.
Автоматическая переменная $Error
В PowerShell существует много автоматических переменных, и одна из них – это автоматическая переменная $Error
. PowerShell использует переменную $Error
, чтобы хранить все ошибки, с которыми встречается в сеансе. Переменная $Error
является массивом ошибок, отсортированным по наиболее недавним.
Когда вы впервые открываете сеанс PowerShell, переменная $Error
пуста. Вы можете проверить это, вызвав переменную $Error
.

Как видно, переменная $Error
начинает с пустого значения. Но как только возникает ошибка, она добавляется и сохраняется в переменной $Error
.
В приведенном ниже примере ошибка генерируется путем намеренного получения имени службы, которое не существует.

Как видно из вывода выше, сгенерированная ошибка была добавлена в переменную $Error
.
Переменная $Error содержит коллекцию ошибок, созданных в сеансе PowerShell. Каждую ошибку можно получить, вызвав ее по позиции в массиве. Последняя ошибка всегда будет находиться по индексу 0.
Например, последнюю ошибку можно получить с помощью
$Error[0]
.
Свойства объекта $Error
Поскольку все в PowerShell является объектом, переменная $Error
является объектом, а у объектов есть свойства. Перенаправив переменную $Error
в cmdlet Get-Member
, вы увидите список доступных свойств.

Чтобы определить причину ошибки, вы можете просмотреть содержимое свойства InvocationInfo
с помощью следующей команды.

Теперь вы можете сделать то же самое с другими свойствами и узнать, какую дополнительную информацию можно найти!
Завершение ошибок
Завершающие ошибки останавливают поток выполнения, когда они встречаются PowerShell по сравнению с незавершающимися ошибками. Существует несколько способов возникновения завершающей ошибки. Один из примеров – когда вы вызываете командлет с параметром, который не существует.
Как видно на скриншоте ниже, когда выполняется команда Get-Process notepad
, команда допустима, и отображаются детали процесса notepad.

Однако, когда используется параметр, который не существует, например, такой как Get-Process notepad -handle 251
, командлет отображает ошибку, что параметр handle
недопустим. Затем командлет завершает выполнение без отображения деталей процесса notepad
.

Незавершающие ошибки
Незавершающие ошибки – это ошибки, которые не прерывают выполнение сценария или команды. Например, рассмотрим приведенный ниже код. Этот код получает список имен файлов из файла fileslist.txt. Затем сценарий проходит через каждое имя файла, считывает содержимое каждого файла и выводит его на экран.
Содержимое файла filelist.txt – это имена файлов, показанные в списке ниже.
Но что если File_6.log на самом деле не существует? Когда вы запускаете код, вы ожидаете, что произойдет ошибка, потому что сценарий не может найти File_6.log. Ниже показано аналогичное выводимое сообщение.

Как видно на снимке экрана с результатом выше, сценарий смог прочитать первые пять файлов в списке, но при попытке прочитать файл File_6.txt, возникает ошибка. Затем сценарий продолжил чтение оставшихся файлов перед завершением. Он не прервался.
Переменная $ErrorActionPreference
До сих пор вы узнали о прерывающих и непрерывающих ошибках и о том, в чем их различие. Но знали ли вы, что непрерывающуюся ошибку можно принудительно рассматривать как прерывающуюся?
В PowerShell есть концепция, называемая pпеременные ссылки. Эти переменные используются для изменения поведения PowerShell во многих различных ситуациях. Одной из этих переменных является $ErrorActionPreference
.
Переменная $ErrorActionPreference
используется для изменения способа обработки непрерывающихся ошибок в PowerShell. По умолчанию значение $ErrorActionPreference
установлено на Continue
. Изменение значения переменной $ErrorActionPreference
на STOP
заставляет PowerShell рассматривать все ошибки как прерывающиеся.
Используйте приведенный ниже код для изменения значения $ErrorActionPreference
.
Чтобы узнать больше о других допустимых значениях переменной $ErrorActionPreference, посетите PowerShell ErrorActionPreference.
Теперь обратитесь к примеру, использованному в разделе Non-Terminating Errors в данной статье. Сценарий можно изменить, чтобы включить изменение в $ErrorActionPreference
, как показано в коде ниже:
Запуск измененного кода выше будет вести себя иначе, чем раньше, когда значение $ErrorActionPreference
установлено в значение по умолчанию Continue
.

$ErrorActionPreference
variableКак видно на скриншоте результата выше, сценарий смог прочитать первые пять файлов в списке, но когда он попытался прочитать файл File_6.txt, возникла ошибка, потому что файл не был найден. Затем сценарий завершился, и остальные файлы не были прочитаны.
Значение
$ErrorActionPreference
действительно только в текущем сеансе PowerShell. Оно сбрасывается в значение по умолчанию при запуске нового сеанса PowerShell.
Общий параметр ErrorAction
Если значение $ErrorActionPreference
применено к сеансу PowerShell, параметр ErrorAction
применяется к любой командлету, поддерживающему общие параметры. Параметр ErrorAction
принимает те же значения, что и переменная $ErrorActionPreference
.
Значение параметра ErrorAction
имеет приоритет над значением переменной $ErrorActionPreference
.
Вернемся и используем тот же код, что и в предыдущем примере. Но на этот раз параметр ErrorAction
добавлен к строке Get-Content
.
После выполнения измененного кода вы увидите, что, несмотря на то, что $ErrorActionPreference
установлен в Continue
, сценарий все равно завершился после возникновения ошибки. Сценарий завершился, потому что значение параметра PowerShell ErrorAction
в Get-Content
установлено в STOP
.

ErrorAction
parameterИспользование блоков PowerShell Try Catch
На этом этапе вы узнали о ошибках PowerShell и о том, как работают переменная $ErrorActionPreference
и параметры ErrorAction
PowerShell. Теперь пришло время узнать о полезной штуке – блоках PowerShell Try Catch Finally
.
Блоки PowerShell try catch
(и необязательный finally block
) представляют собой способ обернуть кусок кода в сеть и перехватить любые ошибки, которые возвращаются.
Ниже приведен синтаксис оператора Try
.
Блок Try
содержит код, который вы хотите, чтобы PowerShell “попытался” выполнить и отследил ошибки. Если код в блоке Try
встречает ошибку, ошибка добавляется в переменную $Error
и затем передается в блок Catch
.
Блок Catch
содержит действия для выполнения при получении ошибки из блока Try
. В операторе Try
может быть несколько блоков Catch
.
Блок Finally
содержит код, который будет выполняться в конце оператора Try
. Этот блок выполняется вне зависимости от того, произошла ли ошибка.
Перехват неуказанных ошибок (все ошибки) с помощью параметра PowerShell ErrorAction
A simple Try
statement contains a Try
and a Catch
block. The Finally
block is optional.
Например, чтобы перехватить неуказанное исключение, параметр Catch
должен быть пустым. Приведенный ниже пример кода использует тот же скрипт, что и в разделе Переменная $ErrorActionPreference, но измененный для использования блоков Try Catch
.
Как видно из приведенного ниже кода, на этот раз оператор foreach
находится внутри блока Try
. Затем блок Catch
содержит код для отображения строки An Error Occurred
, если произошла ошибка. Код в блоке Finally
просто очищает переменную $Error
.
Код выше, после запуска в PowerShell, выдаст следующий вывод, показанный ниже.

Вывод выше показывает, что скрипт столкнулся с ошибкой, выполнил код внутри блока Catch
и затем завершился.
Ошибка была обработана, что и было целью обработки ошибок. Однако отображенная ошибка была слишком общей. Чтобы показать более подробную ошибку, вы можете получить доступ к свойству Exception
ошибки, которая была передана блоком Try
.
Ниже приведен измененный код, в частности код внутри блока Catch
, чтобы отобразить сообщение об исключении из текущей ошибки, которая была передана по каналу передачи данных – $PSItem.Exception.Message
На этот раз, когда запускается измененный выше код, отображаемое сообщение гораздо более описательное.

Перехват конкретных ошибок
Бывают случаи, когда обработка ошибок по умолчанию не является наиболее подходящим подходом. Возможно, вы хотите, чтобы ваш скрипт выполнял действие, зависящее от типа ошибки, с которой он столкнулся.
Как определить тип ошибки? Проверьте значение TypeName
свойства Exception
последней ошибки. Например, чтобы найти тип ошибки из предыдущего примера, используйте эту команду:
Результат выполнения кода выше будет выглядеть как на скриншоте ниже. Как видите, отображается значение TypeName
– System.Management.Automation.ItemNotFoundException
.

Теперь, когда вы знаете тип ошибки, который вам нужно перехватить, измените код так, чтобы он ловил именно эту ошибку. Как вы видите из измененного кода ниже, теперь есть два блока Catch
. Первый блок Catch
перехватывает конкретный тип ошибки (System.Management.Automation.ItemNotFoundException
). В то время как второй блок Catch
содержит общее сообщение об ошибке.
На скриншоте ниже показан вывод измененного кода выше.

Заключение
В этой статье вы узнали ошибках в PowerShell, их свойствах и о том, как можно определить конкретный тип ошибки. Вы также узнали разницу между переменной $ErrorActionPreference
и параметром ErrorAction
в PowerShell и как это влияет на обработку не завершающих ошибок.
Вы также узнали, как использовать блоки Try Catch Finally
в PowerShell для обработки ошибок, будь то конкретные ошибки или общий подход к их обработке.
Приведенные в этой статье примеры демонстрируют только основы работы блоков Try Catch Finally
. Полученные знания, которые, я надеюсь, вы получили из этой статьи, должны дать вам отправную точку для применения обработки ошибок в ваших сценариях.