Try-Catch не работает в PowerShell — причины и решения

Почему Try-Catch может не работать в PowerShell?
Try-Catch ловит ошибки и исключения, но только если ошибка считается “terminating”. Частые причины, по которым Catch не срабатывает:
- Default ErrorAction установлен как Continue — тогда многие ошибки не становятся terminating и Try-Catch их не перехватит.
- Синтаксические ошибки или неверный порядок блоков Try и Catch.
- Поведение конкретного cmdlet или функции: некоторые команды возвращают сообщения об ошибке как non-terminating по умолчанию.
- Неверная логика или использование переменных: ошибка может быть подавлена или переопределена до блока Catch.
Важно: PowerShell различает non-terminating (обычные сообщения об ошибке) и terminating (фатальные) ошибки. Try-Catch работает только с terminating.
Быстрая проверка синтаксиса
- Убедитесь, что вы используете синтаксис, поддерживаемый вашей версией PowerShell.
- Проверьте, что блоки идут в правильном порядке: Try, затем Catch. Допускается блок Finally.
- Пример базового шаблона:
Try {
# код для выполнения
}
Catch {
# код обработки ошибки
}Если синтаксис корректен, переходите к проверке поведения ошибок.
Проверка, ловите ли вы нужный тип ошибки
- Запустите PowerShell от имени администратора.
- Внутри Catch используйте переменную $_ для доступа к объекту ошибки и анализируйте тип исключения.
Пример, который определяет DirectoryNotFoundException:
Try {
Get-ChildItem -Path C:\DoesNotExist
}
Catch {
if ($_.Exception.GetType().Name -eq "DirectoryNotFoundException") {
Write-Output "Directory not found."
}
else {
throw $_.Exception
}
}Если тип исключения не совпадает, Catch может либо не выполниться, либо вызывать повторное выбрасывание (throw).

Установка ErrorAction: когда и как ставить Stop
По умолчанию многие cmdlet работают с -ErrorAction Continue. Чтобы заставить cmdlet генерировать terminating ошибки, укажите -ErrorAction Stop или установите глобально $ErrorActionPreference.
Пример на cmdlet:
Try {
Get-ChildItem -Path C:\DoesNotExist -ErrorAction Stop
}
Catch {
Write-Output $_.Exception.Message
}Альтернативно, для тестовой сессии можно временно выставить:
$previous = $ErrorActionPreference
$ErrorActionPreference = "Stop"
# выполнить набор команд
$ErrorActionPreference = $previousВажно: глобальное изменение $ErrorActionPreference может повлиять на другие скрипты. Используйте осторожно.
Корректный тип исключения
Try-Catch по умолчанию ловит объекты-наследники System.Exception. Если библиотека возвращает «не-CLR» ошибки или использует собственный механизм (например, .NET-native errors в специфичных вызовах), стандартный Catch может не сработать. В таких случаях:
- Явно указывайте тип в Catch: Catch [System.Exception] { … }
- Или оборачивайте проблемный вызов в конструкцию, которая преобразует ошибку в System.Exception.

Не допускайте преждевременного завершения скрипта
Если скрипт завершается до исполнения Catch (например, из-за вызова Exit, или из-за ошибки в конструкции, исполняющейся до Try), Catch не выполнится.
Советы:
- Не используйте Exit внутри Try перед потенциальной ошибкой.
- Если Catch должен позволить дальнейшее выполнение, добавьте Continue в циклах или логике, где это уместно.
Пример с Continue:
Try {
Get-ChildItem -Path C:\DoesNotExist
}
Catch {
Write-Output $_.Exception.Message
Continue
}Try-Catch-Finally: когда добавить Finally
Finally выполняется всегда, независимо от того, произошло ли исключение. Это удобно для очистки ресурсов (закрыть файловые дескрипторы, удалить временные файлы и т.п.).
Try {
# Ваш код
}
Catch [System.Exception] {
# Обработка исключения
}
Finally {
# Очистка
}Альтернативы и дополнительные подходы
- trap { } — старый механизм обработки ошибок, работает на уровне скрипта; полезен для совместимости, но более громоздок.
- Set-StrictMode — помогает найти проблемные места с неинициализированными переменными.
- Проверка возвращаемых кодов и объектов: у некоторых cmdlet нет исключений, но они возвращают объекты с полем Success/Status.
Чеклист: быстрое исправление проблемы (для разработчика или администратора)
- Проверить синтаксис Try/Catch/Finally.
- Запустить PowerShell как администратор.
- Установить -ErrorAction Stop на проблемном cmdlet или временно выставить $ErrorActionPreference = “Stop”.
- Внутри Catch вывести $.Exception.Message и $.Exception.GetType().Name для диагностики.
- Убедиться, что нет Exit или других причин преждевременного завершения.
- Если нужно — добавить Finally для очистки.
Критерии приёмки
- При намеренно вызванной ошибке с -ErrorAction Stop блок Catch выполняется и возвращает ожидаемое сообщение.
- Скрипт не завершает процесс до обработки ошибки (нет неожиданных Exit).
- Логирование в Catch фиксирует тип исключения и текст ошибки.
Тесты и сценарии приёма
- Тест A — non-existent путь:
- Команда: Get-ChildItem -Path C:\DoesNotExist -ErrorAction Stop
- Ожидаемое: Catch выполняется, выводит сообщение об отсутствии каталога.
- Тест B — non-terminating ошибка без -ErrorAction:
- Команда: Get-Command некорректный параметр (по умолчанию Continue)
- Ожидаемое: Catch не выполняется; подтвердите, что при добавлении -ErrorAction Stop Catch срабатывает.
- Тест C — проверка типа исключения:
- В Catch вывести $_.Exception.GetType().Name и сравнить с ожидаемым.
Ролевые чеклисты
Developer:
- Локально протестировать сценарии с -ErrorAction Stop.
- Добавить логирование ошибок и повторный throw в Catch, если нужно поднять ошибку выше.
Sysadmin / Scripter:
- Не менять глобально $ErrorActionPreference в общесистемных профилях.
- Использовать Try-Catch-Finally для операций с файлами, реестром, удалёнными ресурсами.
Ментальные модели
- Ошибка = сообщение, не всегда «фатальная». Только «terminating» ошибки идут в Catch.
- -ErrorAction Stop превращает non-terminating в terminating для данного вызова.
- $ErrorActionPreference действует глобально; -ErrorAction действует локально на cmdlet.
Когда Try-Catch не подойдёт (контрпримеры)
- Когда cmdlet не генерирует исключения, а возвращает статус через объект: тогда нужно проверять возвращаемый объект, а не полагаться на Catch.
- Когда внешняя библиотека обрабатывает ошибки внутри и не пробрасывает их наружу.
Шаблон быстрого отладки (SOP)
- Вставьте в блок Catch временную отладочную печать:
Catch {
Write-Output "=== CATCH ENTERED ==="
Write-Output $_.Exception.GetType().Name
Write-Output $_.Exception.Message
}- Запустите проблемный фрагмент с -ErrorAction Stop.
- Смотрите вывод и исправляйте логику по типу исключения.
Глоссарий (в 1 строку)
- Try: блок, где выполняется код, который может сгенерировать исключение.
- Catch: блок, который выполняется при возникновении terminating ошибки.
- Finally: блок, который выполняется всегда после Try/Catch.
- terminating / non-terminating: классификация ошибок в PowerShell.
- $ErrorActionPreference / -ErrorAction: параметры управления поведением ошибок.
Полезные примечания
Важное: не меняйте глобальные настройки в профиле без согласования. Для единичных вызовов предпочитайте параметр -ErrorAction Stop.
Связанные темы:
- How to Open and Use DirectX Diagnostic Tool (dxdiag) in Windows 11
- How to Use Xbox Game Bar in Windows 11 (Full Guide for Beginners)
- How to Win Bing Quiz: Easy Steps to Always Get It Right
- How To Sign Up and Create A New Gmail Account [Easy Guide]
- How to Login Into Spectrum Email: Full Guide for Former Time Warner & Charter
Если остались вопросы по Try-Catch или нужен разбор конкретного скрипта — опишите симптомы и вставьте минимальный воспроизводимый пример. Мы поможем с диагностикой.
Похожие материалы
Как надёжно удалять файлы в Windows
Как использовать Bitmoji Reactions в Snapchat
Ввод специальных символов в OS X за два нажатия
Включение TRIM для SSD в Windows 11
Скачивание файлов в Safari на iPhone и iPad