Пуленепробиваемая обработка исключений Powershell - PullRequest
4 голосов
/ 22 марта 2020

Я переносю очень большой скрипт на основе функций в классы и одновременно пытаюсь поднять игру на ловушку ошибок. Код выполняется либо на удаленных компьютерах посредством заданий, либо автоматически и прозрачно при входе пользователя в систему, при этом файлы журнала являются единственным средством сообщения о проблемах. Текущая версия (на основе функций) имеет некоторые ошибки, которые приводят к необработанным исключениям, что означает, что проблемы никогда не попадают в журнал. Код считывает предоставленный пользователем файл 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

Работает, не работает. Нужно понять, почему я не могу выбросить исключение с двумя аргументами. Но ... прогресс.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...