Я переносю очень большой скрипт на основе функций в классы и одновременно пытаюсь поднять игру на ловушку ошибок. Код выполняется либо на удаленных компьютерах посредством заданий, либо автоматически и прозрачно при входе пользователя в систему, при этом файлы журнала являются единственным средством сообщения о проблемах. Текущая версия (на основе функций) имеет некоторые ошибки, которые приводят к необработанным исключениям, что означает, что проблемы никогда не попадают в журнал. Код считывает предоставленный пользователем файл XML для обработки данных, и мне нужно предоставить содержательную обратную связь, чтобы можно было обращаться к данным или структуре данных. Мои цели в общем ... 1: Поймать ВСЕ исключения. 2: визуально различать «ожидаемые» исключения; где я предоставляю некоторую полезную информацию в журнале, чтобы позволить пользователю устранять неполадки и «неожиданные» исключения; где я предоставляю имя скрипта и номер строки, чтобы помочь мне отследить ошибки. 3: Со временем переместите как можно больше предметов из «неожиданного» в «ожидаемый».
Учитывая эти цели, я обдумываю несколько вещей, и мне кажется, что я не знаю достаточно, чтобы будь уверен, что я прав в принятии решений. 1: $ErrorActionPreference=Stop
Исторически советом было НЕ устанавливать действие по глобальной ошибке, а делать это вместо этого на индивидуальной основе. Но с учетом того, что в каждой ситуации, когда я МОГУ установить ее остановку, это произойдет, кажется, что этот совет действительно больше относится к быстрым «сценариям», тогда как я в основном использую PS для написания «программы», а глобальная остановка - это лучший ответ?
2: Учитывая сценарий, подобный этому, где у меня есть исключение в служебном методе (нет, я не реализую класс здесь, я пытаюсь упростить пример для примера, но, надеюсь, концепция все еще ясна) ...
$path = '\\Server\InvalidFolder|'
try {
Test-Path $path -errorAction:stop
} catch [System.ArgumentException] {
throw [Custom.ExpectedException] "Error: Invalid characters in path - $invalidCharacters"
} catch {
# Generic error trap
throw [Custom.UnexpectedException] "Unexpected Error: $($_.ScriptStackTrace) $($_.Exception.Message)"
}
Мне кажется, что я хочу / нужно сделать, это создать несколько пользовательских типов ошибок, чтобы я мог перехватывать различные ошибки Powershell и преобразовывать их в мои типы, которые Затем я выбрасываю, и вызывающий код имеет свою собственную команду try / catch, которая затем форматирует и отправляет в журнал. Это правильный подход, или я упускаю какой-то лучший вариант? 3: Предполагая, что это даже возможно / желательно, как можно создавать пользовательские типы исключений? Мой Google-Fu подвел меня, и мне стало интересно, не могу ли я найти что-нибудь, потому что это не может / не должно быть сделано.
РЕДАКТИРОВАТЬ: Что касается пользовательских типов исключений go, это выглядит нормально.
class PxException : Exception {
PxException() {
}
PxException([string] $message): base($message) {
}
PxException([string] $message, [Exception] $inner) : base($message, $inner) {
}
}
$path = '\\Server\InvalidFolder|'
try {
Test-Path $path -errorAction:stop
} catch [System.ArgumentException] {
Write-Host "Error: $($_.Exception.Message)"
throw [PxException] "Px expected exception"
} catch {
# Standard Px error trap
Write-Host "Unexpected Error: $($_.ScriptStackTrace)"
Write-Host "$($_.Exception.Message)"
}
Все еще удивляюсь, что это ПРАВИЛЬНЫЙ способ, но это, очевидно, путь, и это хороший знак.
РЕДАКТИРОВАТЬ 2: Итак, это работает
class PxException : Exception {
PxException() {}
PxException([string] $message) : base($message) {}
PxException([string] $message, [Exception] $inner) : base($message, $inner) {}
}
Но когда я пытаюсь реализовать InvocationInfo в моем пользовательском типе, он barfs ...
class PxException : Exception {
PxException() {}
PxException([string] $message) : base($message) {}
PxException([string] $message, [InvocationInfo] $InvocationInfo) : base($message, $InvocationInfo) {}
PxException([string] $message, [Exception] $inner) : base($message, $inner) {}
}
[InvocationInfo]
не распознается как тип. Даже если у меня есть using namespace System;
, где, как мне кажется, определено InvocationInfo.
РЕДАКТИРОВАТЬ 3: GetType()
на помощь. Это работает. PxException([string] $message, [System.Management.Automation.InvocationInfo] $InvocationInfo) : base($message, $InvocationInfo) {}
Нет using
требуется. По крайней мере, до того, как избавиться от ошибки в определении класса исключения. Но
$InvocationInfo = $_.InvocationInfo
throw [PxException] "Px expected exception" $InvocationInfo
Работает, не работает. Нужно понять, почему я не могу выбросить исключение с двумя аргументами. Но ... прогресс.