Подавление ошибок powershell

В Powershell существует несколько уровней ошибок и несколько способов их обработать. Проблемы одного уровня (Non-Terminating Errors) можно решить с помощью привычных для Powershell команд. Другой уровень ошибок (Terminating Errors) решается с помощью исключений (Exceptions) стандартного, для большинства языков, блока в виде Try, Catch и Finally. 

Как Powershell обрабатывает ошибки

До рассмотрения основных методов посмотрим на теоретическую часть.

Автоматические переменные $Error

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

Get-TestTest
$Error
$Error.Count

Переменная $Error в Powershell

При отсутствии каких либо ошибок мы бы получили пустой ответ, а счетчик будет равняться 0:

Счетчик ошибок с переменной $Error в Powershell

Переменная $Error являет массивом и мы можем по нему пройтись или обратиться по индексу что бы найти нужную ошибку:

$Error[0]

foreach ($item in $Error){$item}

Вывод ошибки по индексу в Powershell c $Error

Свойства объекта $Error

Так же как и все что создается в Powershell переменная $Error так же имеет свойства (дополнительную информацию) и методы. Названия свойств и методов можно увидеть через команду Get-Member:

$Error | Get-Member

Свойства переменной $Error в Powershell

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

$Error[0].InvocationInfo

Детальная информация об ошибке с $Error в Powershell

Методы объекта $Error

Например мы можем очистить логи ошибок используя clear:

$Error.clear()

Очистка логов об ошибке в Powershell с $Error

Критические ошибки (Terminating Errors)

Критические (завершающие) ошибки останавливают работу скрипта. Например это может быть ошибка в названии командлета или параметра. В следующем примере команда должна была бы вернуть процессы «svchost» дважды, но из-за использования несуществующего параметра ‘—Error’ не выполнится вообще:

'svchost','svchost' | % {Get-Process -Name $PSItem} --Error 

Критические ошибки в Powershell Terminating Errors

Не критические ошибки (Non-Terminating Errors)

Не критические (не завершающие) ошибки не остановят работу скрипта полностью, но могут вывести сообщение об этом. Это могут быть ошибки не в самих командлетах Powershell, а в значениях, которые вы используете. На предыдущем примере мы можем допустить опечатку в названии процессов, но команда все равно продолжит работу:

'svchost111','svchost' | % {Get-Process -Name $PSItem}

Не критические ошибки в Powershell Non-Terminating Errors

Как видно у нас появилась информация о проблеме с первым процессом ‘svchost111’, так как его не существует. Обычный процесс ‘svchost’ он у нас вывелся корректно.

Параметр ErrorVariable

Если вы не хотите использовать автоматическую переменную $Error, то сможете определять свою переменную индивидуально для каждой команды. Эта переменная определяется в параметре ErrorVariable:

'svchost111','svchost' | % {Get-Process -Name $PSItem } -ErrorVariable my_err_var
$my_err_var

Использование ErrorVariable в Powershell

Переменная будет иметь те же свойства, что и автоматическая:

$my_err_var.InvocationInfo

Свойства  ErrorVariable в Powershell

Обработка некритических ошибок

У нас есть два способа определения последующих действий при ‘Non-Terminating Errors’. Это правило можно задать локально и глобально (в рамках сессии). Мы сможем полностью остановить работу скрипта или вообще отменить вывод ошибок.

Приоритет ошибок с $ErrorActionPreference

Еще одна встроенная переменная в Powershell $ErrorActionPreference глобально определяет что должно случится, если у нас появится обычная ошибка. По умолчанию это значение равно ‘Continue’, что значит «вывести информацию об ошибке и продолжить работу»:

$ErrorActionPreference

Определение $ErrorActionPreference в Powershell

Если мы поменяем значение этой переменной на ‘Stop’, то поведение скриптов и команд будет аналогично критичным ошибкам. Вы можете убедиться в этом на прошлом скрипте с неверным именем процесса:

$ErrorActionPreference = 'Stop'
'svchost111','svchost' | % {Get-Process -Name $PSItem}

Определение глобальной переменной $ErrorActionPreference в Powershell

Т.е. скрипт был остановлен в самом начале. Значение переменной будет храниться до момента завершения сессии Powershell. При перезагрузке компьютера, например, вернется значение по умолчанию.

Ниже значение, которые мы можем установить в переменной $ErrorActionPreference:

  • Continue — вывод ошибки и продолжение работы;
  • Inquire — приостановит работу скрипта и спросит о дальнейших действиях;
  • SilentlyContinue — скрипт продолжит свою работу без вывода ошибок;
  • Stop — остановка скрипта при первой ошибке.

Самый частый параметр, который мне приходится использовать — SilentlyContinue:

$ErrorActionPreference = 'SilentlyContinue'
'svchost111','svchost' | % {Get-Process -Name $PSItem}

Игнорирование ошибок в Powershell с ErrorActionPreference и SilentlyContinue

Использование параметра ErrorAction

Переменная $ErrorActionPreference указывает глобальный приоритет, но мы можем определить такую логику в рамках команды с параметром ErrorAction. Этот параметр имеет больший приоритет чем $ErrorActionPreference. В следующем примере, глобальная переменная определяет полную остановку скрипта, а в параметр ErrorAction говорит «не выводить ошибок и продолжить работу»:

$ErrorActionPreference = 'Stop'
'svchost111','svchost' | % {Get-Process -Name $PSItem -ErrorAction 'SilentlyContinue'}

Использование параметра ErrorAction в ошибках с Powershell

Кроме ‘SilentlyContinue’ мы можем указывать те же параметры, что и в переменной $ErrorActionPreference. 

Значение Stop, в обоих случаях, делает ошибку критической.

Обработка критических ошибок и исключений с Try, Catch и Finally

Когда мы ожидаем получить какую-то ошибку и добавить логику нужно использовать Try и Catch. Например, если в вариантах выше мы определяли нужно ли нам отображать ошибку или останавливать скрипт, то теперь сможем изменить выполнение скрипта или команды вообще. Блок Try и Catch работает только с критическими ошибками и в случаях если $ErrorActionPreference или ErrorAction имеют значение Stop.

Например, если с помощью Powershell мы пытаемся подключиться к множеству компьютеров один из них может быть выключен — это приведет к ошибке. Так как эту ситуацию мы можем предвидеть, то мы можем обработать ее. Процесс обработки ошибок называется исключением (Exception).

Синтаксис и логика работы команды следующая:

try {
    # Пытаемся подключиться к компьютеру
}
catch [Имя исключения 1],[Имя исключения 2]{
    # Раз компьютер не доступен, сделать то-то
}
finally {
    # Блок, который выполняется в любом случае последним
}

Блок try мониторит ошибки и если она произойдет, то она добавится в переменную $Error и скрипт перейдет к блоку Catch. Так как ошибки могут быть разные (нет доступа, нет сети, блокирует правило фаервола и т.д.) то мы можем прописывать один блок Try и несколько Catch:

try {
    # Пытаемся подключится
}
catch ['Нет сети']['Блокирует фаервол']{
    # Записываем в файл
}
catch ['Нет прав на подключение']{
    # Подключаемся под другим пользователем
}

Сам блок finally — не обязательный и используется редко. Он выполняется самым последним, после try и catch и не имеет каких-то условий.

Catch для всех типов исключений

Как и было показано выше мы можем использовать блок Catch для конкретного типа ошибок, например при проблемах с доступом. Если в этом месте ничего не указывать — в этом блоке будут обрабатываться все варианты ошибок:

try {
   'svchost111','svchost' | % {Get-Process -Name $PSItem -ErrorAction 'Stop'}
}
catch {
   Write-Host "Какая-то неисправность" -ForegroundColor RED
}

Игнорирование всех ошибок с try и catch в Powershell

Такой подход не рекомендуется использовать часто, так как вы можете пропустить что-то важное.

Мы можем вывести в блоке catch текст ошибки используя $PSItem.Exception:

try {
   'svchost111','svchost' | % {Get-Process -Name $PSItem -ErrorAction 'Stop'}
}
catch {
   Write-Host "Какая-то неисправность" -ForegroundColor RED
   $PSItem.Exception
}

Переменная PSITem в блоке try и catch в Powershell

Переменная $PSItem хранит информацию о текущей ошибке, а глобальная переменная $Error будет хранит информацию обо всех ошибках. Так, например, я выведу одну и ту же информацию:

$Error[0].Exception

Вывод сообщения об ошибке в блоке try и catch в Powershell

Создание отдельных исключений

Что бы обработать отдельную ошибку сначала нужно найти ее имя. Это имя можно увидеть при получении свойств и методов у значения переменной $Error:

$Error[0].Exception | Get-Member

Поиск имени для исключения ошибки в Powershell

Так же сработает и в блоке Catch с $PSItem:

Наименование ошибок для исключений в Powershell

Для вывода только имени можно использовать свойство FullName:

$Error[0].Exception.GetType().FullName

Вывод типа ошибок и их названия в Powershell

Далее, это имя, мы вставляем в блок Catch:

try {
   'svchost111','svchost' | % {Get-Process -Name $PSItem -ErrorAction 'Stop'}
}
catch [Microsoft.PowerShell.Commands.ProcessCommandException]{
   Write-Host "Произошла ошибка" -ForegroundColor RED
   $PSItem.Exception
}

Указываем исключение ошибки в блоке Try Catch Powershell

Так же, как и было описано выше мы можем усложнять эти блоки как угодно указывая множество исключений в одном catch.

Выброс своих исключений

Иногда нужно создать свои собственные исключения. Например мы можем запретить добавлять через какой-то скрипт названия содержащие маленькие буквы или сотрудников без указания возраста и т.д. Способов создать такие ошибки — два и они тоже делятся на критические и обычные.

Выброс с throw

Throw — выбрасывает ошибку, которая останавливает работу скрипта. Этот тип ошибок относится к критическим. Например мы можем указать только текст для дополнительной информации:

$name = 'AD.1'

if ($name -match '.'){
   throw 'Запрещено использовать точки в названиях'
}

Выброс ошибки с throw в Powershell

Если нужно, то мы можем использовать исключения, которые уже были созданы в Powershell:

$name = 'AD.1'

if ($name -like '*.*'){
   throw [System.IO.FileNotFoundException]'Запрещено использовать точки в названиях'
}

Выброс ошибки с throw в Powershell

Использование Write-Error

Команда Write-Error работает так же, как и ключ ErrorAction. Мы можем просто отобразить какую-то ошибку и продолжить выполнение скрипта:

$names = @('CL1', 'AD.1', 'CL3')

foreach ($name in $names){
   if ($name -like '*.*'){
      Write-Error -Message 'Обычная ошибка'
   }
   else{
      $name
   }
}

Использование Write-Error для работы с исключениями в Powershell

При необходимости мы можем использовать параметр ErrorAction. Значения этого параметра были описаны выше. Мы можем указать значение ‘Stop’, что полностью остановит выполнение скрипта:

$names = @('CL1', 'AD.1', 'CL3')

foreach ($name in $names){
   if ($name -like '*.*'){
      Write-Error -Message 'Обычная ошибка' -ErrorAction 'Stop'
   }
   else{
      $name
   }
}

Использование Write-Error и Stop в Powershell

Отличие команды Write-Error с ключом ErrorAction от обычных команд в том, что мы можем указывать исключения в параметре Exception:

Write-Error -Message 'Обычная ошибка' -ErrorAction 'Stop'

Write-Error -Message 'Исключение' -Exception [System.IO.FileNotFoundException] -ErrorAction 'Stop'

Свойства Write-Errror в Powershell

В Exception мы так же можем указывать сообщение. При этом оно будет отображаться в переменной $Error:

Write-Error -Exception [System.IO.FileNotFoundException]'Моё сообщение'

Свойства Write-Errror в Powershell 

Теги:

#powershell

#ошибки

Для начала определимся, что такое обработка ошибок вообще. В общем случае ошибка — это поведение программы или скрипта, отличное от запланированного. Совсем избежать ошибок не очень возможно, поэтому надо предвидеть, где они могут возникнуть и писать код так, чтобы при возникновении ошибки можно было перехватить ее, проанализировать и определить дальнейшее поведение скрипта.  Именно это обычно и подразумевается под обработкой ошибок.

В PowerShell ошибки делятся на два типа: прерывающие (Terminating) и непрерывающие (Non-Terminating). Как следует из названия, непрерывающие ошибки позволяют продолжить выполнение команды, тогда как при возникновении прерывающей ошибки дальнейшее продолжение выполнения команды невозможно. К примеру, у нас есть файл со списком служб, которые необходимо перезапустить следующей командой:

Get-Content -Path C:\Files\services.txt | Restart-Service

Предположим, что перезапуск одной из перечисленных служб по какой либо причине невозможен. Тем не менее можно продолжать выполнение задачи, поскольку остальные службы доступны и их можно перезапустить. Это пример непрерывающей ошибки.

А теперь представьте, что у нас нет прав на открытие этого файла, и соответственно прочитать список служб мы не можем. В этой ситуации продолжение работы невозможно, т.е. это прерывающая ошибка.

PowerShell позволяет обрабатывать оба эти типа ошибок. Большинство ошибок в PowerShell непрерывающие, и сегодня речь пойдет о том, как их обрабатывать.

Обработка непрерывающих ошибок

Для получения ошибки возьмем службу с ″оригинальным″ названием Service. Поскольку службы этой на сервере нет, то обращение к ней стабильно будет генерировать ошибку. Запросим данные о нескольких службах командой:

Get-Service service,spooler

Как видно из примера, PowerShell не нашел службу Service, о чем выдал ошибку и затем продолжил выполнение команды. Давайте разберемся, почему команда повела себя именно так и как это поведение изменить.

обработка ошибки по умолчанию

За поведение команды при возникновении ошибки отвечает параметр ErrorAction, который может принимать одно из пяти значений:

• Continue;
• SilentlyContinue;
• Stop;
• Ignore;
• Inquire.

Примечание. Еще у ErrorAction может быть значение Suspend. Но это значение может применяться только к рабочим процессам (workflows), поэтому в рамках данной статьи речь о нем не пойдет.

Значение Continue означает, что при возникновении ошибки информация об этом будет выведена на экран (отправлена в поток вывода Error) и добавлена в автоматическую переменную $Error, после чего выполнение команды будет продолжено. Надо сказать, что Continue — это действие, определенное в сеансе по умолчанию, поэтому его можно не указывать явно.

обработка ошибки, режим Continue

При значении SilentlyContinue информация об ошибке добавляется в переменную $Error, но не выводится на экран. При этом команда продолжает выполняться дальше, также как и в предыдущем случае.

обработка ошибки, режим SilentlyContinue

Значение Stop останавливает дальнейшее выполнение команды при возникновении ошибки. И наоборот, значение Ignore полностью игнорирует возникновение ошибки, при этом не выводится сообщение на экран и не производится запись в $Error. Это значение появилось в PowerShell 3.0.

Обработка ошибок в режимах Stop и Ignore

Inquire — наиболее интересное значение ErrorAction. Если задать это значение, то при возникновении ошибки предлагается на выбор несколько действий: продолжить (Yes), продолжить не смотря на эту и все последующие ошибки (Yes to All), остановить (Halt) или приостановить (Suspend) выполнение команды.

Самый необычный эффект дает Suspend, при выборе которого открывается параллельный сеанс (Nested Namespace). Определить его можно по значку >>. Nested Namespace представляет из себя дочерний процесс, в котором можно полноценно работать — выполнять команды, запускать скрипты и т.п. Этот режим удобно использовать для отладки скриптов, например можно по быстрому исправить причину ошибки и продолжить выполнение. Для выхода из Nested Namespace достаточно набрать exit и выбрать необходимое действие.

Обработка ошибки в режиме Inquire

Примечание. У параметра ErrorAction есть алиас — EA. Кроме того, вместо названия параметра можно указывать числовые значения: 0 (SilentlyContinue), 1 (Stop), 2 (Continue), 3 (Inquire). Так например, вместо:

Get-Service service,spooler -ErrorAction SilentlyContinue

можно написать так:

Get-Service service,spooler -EA 0

Переменные для обработки ошибок

Как я уже говорил, если не указывать параметр ErrorAction, то для команды действует режим обработки ошибок, определенный в сеансе. Этот режим задается переменной $ErrorActionPreference, которая по умолчанию имеет значение Continue. При желании можно переопределить режим для всего сеанса, задав переменной $ErrorActionPreference нужное значение.

Политика обработки ошибок по умолчанию

Все ошибки PowerShell сохраняет в автоматическую переменную $Error. Это глобальная переменная, которая представляет из себя массив строк, содержащий записи обо всех ошибках в текущем сеансе. Каждая новая ошибка добавляется в начало массива, соответственно для просмотра последней ошибки надо обратиться к самому первому элементу массива $Error[0].

$Error имеет свои свойства и методы, которые можно использовать. Например, посмотреть общее количество ошибок в текущем сеансе можно командой $Error.Count, а очистить список — командой $Error.Clear().

переменная $Error

Переменная $Error не безразмерна, по умолчанию она хранит не более 256 ошибок. При превышении этого количества наиболее старые ошибки будут затираться. При необходимости количество записей в переменной $Error можно увеличить, изменив значение другой переменной $MaximumErrorCount.

Кроме $Error для хранения ошибок допускается задавать собственные переменные. Сделать это можно с помощью параметра ErrorVariable, например так:

Get-Service service,spooler -ErrorAction SilentlyContinue -ErrorVariable var

Обратите внимание, что имя переменной в команде задается без знака $, хотя в дальнейшем к ней обращаемся как к обычной переменной $var.

назначение собственной переменной для хранения ошибок

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

Пока все, а в следующей части пойдет о способах обработки прерывающих ошибок.

  1. Introduction to Error Action in PowerShell
  2. Use the -ErrorAction Parameter in PowerShell
  3. Setting Error Action Preferences in PowerShell

Suppressing PowerShell Errors

Whether we want to ignore error messages or terminate a script’s execution when an error occurs, Windows PowerShell has plenty of options for dealing with errors. This article will discuss multiple techniques in handling and suppressing errors.

Introduction to Error Action in PowerShell

Even though it is effortless to suppress Windows PowerShell errors, doing so isn’t always the best option (although it can be). If we carelessly tell PowerShell to hide errors, it can cause our script to behave unpredictably.

Suppressing error messages also makes troubleshooting and information gathering a lot more complicated. So tread lightly and be careful about using the following snippets that you will see in this article.

Use the -ErrorAction Parameter in PowerShell

The most common method for dealing with errors is to append the -ErrorAction parameter switch to a cmdlet. The -ErrorAction parameter switch lets PowerShell tell what to do if the cmdlet produces an error.

Command:

Get-Service 'svc_not_existing' -ErrorAction SilentlyContinue

In the command above, we are querying for a service that doesn’t exist. Usually, PowerShell will throw an error if the service doesn’t exist.

Since we use the -ErrorAction parameter, the script will continue as expected, like it doesn’t have an error.

Setting Error Action Preferences in PowerShell

If we need a script to behave in a certain way (such as suppressing errors), we might consider setting up some preference variables. Preference variables act as configuration settings for PowerShell.

We might use a preference variable to control the number of history items that PowerShell retains or force PowerShell to ask the user before performing specific actions.

For example, here is how you can use a preference variable to set the -ErrorAction parameter to SilentlyContinue for the entire session.

Command:

$ErrorActionPreference = 'SilentlyContinue'

There are many other error actions that we can specify for the ErrorAction switch parameter.

  • Continue: PowerShell will display the error message, but the script will continue to run.
  • Ignore: PowerShell does not produce any error message, writes any error output on the host, and continues execution.
  • Stop: PowerShell will display the error message and stop running the script.
  • Inquire: PowerShell displays the error message but will ask for confirmation first if the user wants to continue.
  • SilentlyContinue: PowerShell silently continues with code execution if the code does not work or has non-terminating errors.
  • Suspend: PowerShell suspends the workflow of the script.

As previously mentioned, the -ErrorAction switch has to be used in conjunction with a PowerShell cmdlet. For instance, we used the Get-Process cmdlet to demonstrate how the ErrorAction switch works.

RRS feed

  • Remove From My Forums
  • Question

  • Hello All,

    How can I remove the warnings from my powershell result output.

    I have this warnings in my powershell and I need to remove this from the output, How can I do that?

    Regards

Answers

    • Marked as answer by
      JPFG
      Monday, September 23, 2013 10:44 AM

All replies

  • could you try this option

    -WarningAction SilentlyContinue


    Satheesh
    My Blog

    • Edited by
      Satheesh Variath
      Monday, September 23, 2013 10:01 AM
      code

  • Try to use the -ErrorAction:silentlycontinue or -WarningAction:silentlycontinu parameters ?

    You can read more about these if you type help about_Common_Parameters in PowerShell

  • thanks for your help,

    The warnings already disapear, but now I have another error, how can I remove this error from my script?

    The error is:

    Another question, How can I get only the value {Owner} from my result?

    Regards

    • Marked as answer by
      JPFG
      Monday, September 23, 2013 10:44 AM

Понравилась статья? Поделить с друзьями:

Интересное по теме:

  • Подбор кода орион про ошибка
  • Под фундаментальной ошибкой атрибуции понимают
  • Подвести резюме лексическая ошибка
  • Под тенистыми деревьями удобно примостились туристы ошибка
  • Подвести результаты встречи лексическая ошибка

  • 0 0 голоса
    Рейтинг статьи
    Подписаться
    Уведомить о
    guest

    0 комментариев
    Старые
    Новые Популярные
    Межтекстовые Отзывы
    Посмотреть все комментарии