Обработка ошибок

Завершено

Итак, вы увидели, как добавление параметров и конструкций управления потоком может сделать сценарии более универсальными и надежными в использовании. Но иногда в сценариях могут возникать ошибки. Необходим способ обработки этих ошибок.

Здесь нужно учитывать несколько факторов:

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

  • Насколько серьезна ошибка. Существуют различные виды сообщений об ошибках. Некоторые из них больше похожи на предупреждения о каких-то нарушениях. Другие более серьезны, и пользователь действительно должен обратить на них внимание. Метод обработки ошибок зависит от типа ошибки. Подход может быть любым: от вывода сообщения до повышения уровня серьезности и потенциальной остановки выполнения сценария.

ошибки

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

Существует два типа ошибок, которые могут возникать при выполнении PowerShell:

  • Неустранимая ошибка. Ошибка этого типа приведет к остановке выполнения кода в строке, в которой произошла ошибка. Этот тип ошибки можно обрабатывать с помощью Try-Catch или Trap. Если ошибка не обработана, в этот момент сценарий прекратит выполнение кода, и никакие инструкции не будут выполняться.

    Примечание.

    Конструкция Trap не рассматривается в данном модуле. Для получения дополнительной информации см. раздел Ловушка.

  • Устранимая ошибка. Этот тип ошибки уведомляет пользователя о нарушении, но выполнение сценария продолжится. Этот тип ошибки можно повысить до уровня неустранимой ошибки.

Управление ошибками с помощью Try/Catch/Finally

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

Существуют три связанные конструкции, с помощью которых можно управлять ошибками этого типа:

  • Try. Блок Try будет использоваться для инкапсуляции одной или нескольких инструкций. Вы поместите код, который требуется выполнить, например код, который записывает данные в источник, внутри фигурных скобок. Объект Try должен иметь по меньшей мере один блок Catch или Finally. Это выглядит так:

    Try {
       # Statement. For example, call a command.
       # Another statement. For example, assign a variable.
    }
    
  • Catch. Это ключевое слово будет использоваться для перехвата или управления ошибкой при ее возникновении. Затем вы просмотрите объект исключения, чтобы понять, ошибка какого типа возникла, где она появилась и возможно ли возобновление выполнение сценария. Код Catch находится непосредственно после Try. При желании можно включить более одного Catch — по одному для каждого типа ошибки. Приведем пример:

    Try {
       # Do something with a file.
    } Catch [System.IO.IOException] {
       Write-Host "Something went wrong"
    }  Catch {
       # Catch all. It's not an IOException but something else.
    }
    

    Сценарий пытается выполнить команду, которая выполняет некоторые операции ввода-вывода. Первый Catch перехватывает ошибку определенного типа: [System.IO.IOException]. Последний Catch перехватывает все, что не является [System.IO.IOException].

  • Finally. Инструкции в этом блоке будут выполняться независимо от того, возникают ли ошибки. Скорее всего, вы будете редко использовать этот блок, но он может быть полезен, например, для очистки ресурсов. Чтобы использовать его, добавьте его на последнее место:

    Try {
       # Do something with a file.
    } Catch [System.IO.IOException] {
       Write-Host "Something went wrong"
    }  Catch {
       # Catch all. It's not an IOException but something else.
    } Finally {
       # Clean up resources.
    }
    

Проверка ошибок

Мы говорили об объектах исключений в контексте перехвата ошибок. Эти объекты можно использовать для проверки нарушений и принятия соответствующих мер. Объект исключения включает:

  • Сообщение. Сообщение содержит краткое описание проблемы.

  • Трассировка стека. Трассировка стека позволяет отследить, какие инструкции выполнялись перед возникновением ошибки. Представьте, что у вас есть вызов функции A, затем B и C. Сценарий перестает отвечать на запросы на этапе вызова функции C. Трассировка стека содержит эту последовательность вызовов.

  • Строка, вызвавшая ошибку. Объект исключения также указывает, в какой строке выполнялся код сценария при возникновении ошибки. Эта информация может помочь исправить ошибку.

Итак, как проверить объект исключения? Существует встроенная переменная, $_, имеющая свойство exception. Чтобы получить сообщение об ошибке, например, можно использовать $_.exception.message. В виде кода это выглядит следующим образом:

Try {
     # Do something with a file.
   } Catch [System.IO.IOException] {
     Write-Host "Something IO went wrong: $($_.exception.message)"
   }  Catch {
     Write-Host "Something else went wrong: $($_.exception.message)"
   }

Создание ошибок

В некоторых ситуациях может быть необходимо возникновение ошибки:

  • Устранимые ошибки. При возникновении ошибок такого типа PowerShell просто уведомляет о проблеме, например, используя командлет Write-Error. Выполнение сценария продолжится. Такое поведение может быть неудовлетворительным. Чтобы повысить уровень серьезности ошибки, можно использовать такой параметр, как -ErrorAction, чтобы вызвать ошибку, которую можно перехватить с помощью Try/Catch, например:

    Try {
       Get-Content './file.txt' -ErrorAction Stop
    } Catch {
       Write-Error "File can't be found"
    }
    

    С помощью параметра -ErrorAction и значения Stop можно вызвать ошибку, которую Try/Catch может перехватить.

  • Бизнес-правила. Может возникнуть ситуация, когда код на самом деле продолжает отвечать на запросы, но в коммерческих целях нужно, чтобы он перестал это делать. Представьте, что вы выполняете отбор входных данных и проверяете, является ли параметр путем. В коммерческих целях может быть указано, что допустимы лишь некоторые пути или что путь должен иметь определенный вид. Если проверки не дали результатов, имеет смысл вывести ошибку. В подобной ситуации можно использовать блок Throw:

    Try {
       If ($Path -eq './forbidden') 
       {
         Throw "Path not allowed"
       }
       # Carry on.
    
    } Catch {
       Write-Error "$($_.exception.message)" # Path not allowed.
    }
    
    

    Примечание.

    Как правило, для проверки параметров не следует использовать Throw. Вместо этого используйте атрибуты проверки. Если не удается обеспечить работу кода с этими атрибутами,тогда можно использовать Throw.