Есть ли способ бросить через пользовательский System.Management.Automation.ErrorRecord? - PullRequest
1 голос
/ 05 марта 2020

Я хотел бы добавить пользовательский System.Management.Automation.ErrorRecord с некоторыми дополнительными свойствами: ContextMessage и SqlCmdHeader.

Я пытался создать новый класс, унаследованный от System.Management.Automation.ErrorRecord:

class SqlRequestException : System.Management.Automation.ErrorRecord
{
    [hashtable]$SqlCmdHeader

    [string]$ContextMessage

    SqlRequestException() { }

    SqlRequestException(
        [string]$message,
        [hashtable]$sqlCmdHeader,
        [System.Management.Automation.ErrorRecord]$errorRecord
    ) : base($errorRecord, $null)
    {
        $this.SqlCmdHeader = $sqlCmdHeader
        $this.ContextMessage = $message
    }
}

Но когда я выкидываю ошибку по этому коду:

try
{
    #exceptions is risen here
}
catch
{
    throw ([SqlRequestException]::New(
            "Some context message of exception which will help to understand the error without additional debugging of code",
            $sqlHeader,
            $_))
}

Я попал в вызывающую программу просто System.Management.Automation.ErrorRecord без моих удивительных свойств. Похоже, throw привел мой объект к System.Management.Automation.ErrorRecord и потерял свойства.

Я хотел бы попросить вас, ребята, помочь мне реализовать эту логику c в моем сценарии. Любая помощь будет очень полезна!

Обновление

Я не могу изменить код звонящего. Он всегда анализирует ошибку и записывает ее в журналы:

try
{
    # calling the method from module where I try to throw custom ErrorRecord
}
catch
{
    Write-Log -Text $_
}

Я не могу использовать System.Exception, потому что когда я генерирую созданное исключение, вся оригинальная информация (например, InvocationInfo, ScriptStackTrace и др. c) ) из ErrorRecord потеряно. Я не смог найти исходный код оператора throw, чтобы понять, как именно он работает (может, кто-то может указать мне на это?)

Я вижу, что есть свойство TargetObject, которое можно использовать для хранения некоторых дополнительных информацию, но я не вижу способов поместить что-то в свойство перед оператором throw, так как свойство равно ReadOnly, и я думаю, что свойство не предназначено для хранения дополнительных данных пользователя.

Ответы [ 2 ]

0 голосов
/ 05 марта 2020

Хотя класс System.Management.Automation.ErrorRecord технически не запечатан и в документации не упоминается подклассы, похоже, что подклассы ErrorRecord эффективно не поддерживаются :

Как вы уже поняли, исходный SqlRequestException экземпляр, который вы throw не делает таковым в стеке вызовов, предположительно , поскольку копирует в экземпляр задействован базовый класс.

Подкласс System.Exception вместо и позволяет PowerShell автоматически обернуть ваше исключение в [ErrorRecord] экземпляр, свойство .Exception которого вы можете запросить позже:

# Make your custom exception derive from System.Exception.
class SqlRequestException : System.Exception
{
    [hashtable]$SqlCmdHeader
    [string]$ContextMessage

    # Construct the exception with the one passed as an 
    # argument as the *inner* exception.
    SqlRequestException(
        [string]$contextMessage,
        [hashtable]$sqlCmdHeader,
        [exception]$innerException
    ) : base($innerException.Message, $innerException)
    {
        $this.ContextMessage = $contextMessage
        $this.SqlCmdHeader = $sqlCmdHeader
    }
}

try { # Outer `try` to simulate a caller.
  try # Your code.
  {
      [int]::Parse('not a number') # Sample exception.
  }
  catch
  {
     # Throw your custom exception that wraps the original exception
     # ($_.Exception) via its .InnerException property.
     # PowerShell itself then automatically wraps your custom exception in
     # an [ErrorRecord] instance.
     throw ([SqlRequestException]::New(
              'custom message',
              @{ header1 = 'foo' },
              $_.Exception))
  }
} catch { # The (simulated) caller's catch block.
  # Now you can access your custom properties via $_.Exception.
  @"
Error: $_
Custom properties:
  ContextMessage: $($_.Exception.ContextMessage)
  SqlCmdHeader: $($_.Exception.SqlCmdHeader | Out-String)
"@
}

Выше приведено следующее, показывающее, что оба пользовательских свойства были переданы:

Error: Exception calling "Parse" with "1" argument(s): "Input string was not in a correct format."
Custom properties:
  ContextMessage: custom message
  SqlCmdHeader: 
Name                           Value
----                           -----
header1                        foo

Сообщение пользовательского исключения - это сообщение исходного исключения; чтобы получить подробную информацию об исходном исключении, введите $_.InnerException.

0 голосов
/ 05 марта 2020

Вы можете создать пользовательский объект в блоке catch (вам не нужен собственный класс), что-то вроде этого.

$customobj = New-Object -TypeName psobject 
$customobj | Add-Member -MemberType NoteProperty -Name SQLhead -Value $sqlHeader 
$customobj | Add-Member -MemberType NoteProperty -Name Error -Value $_

Немного больше о создании пользовательских объектов пользовательских объектов

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