有没有办法通过自定义System.Management.Automation.ErrorRecord抛出



我想抛出带有一些附加属性的自定义System.Management.Automation.ErrorRecordContextMessageSqlCmdHeader

我试图创建从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并丢失了属性。

我想请你们帮我在我的脚本中实现这个逻辑。任何帮助都将不胜感激!

更新

我无法更改呼叫者的代码。它总是解析错误并将其写入日志:

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

我不能使用System.Exception,因为当我抛出创建的异常时,来自ErrorRecord的所有原始信息(如InvocationInfoScriptStackTrace等(都会丢失。我找不到throw语句的源代码来理解它的确切工作原理(也许有人可以给我指一下?(

我看到有一个TargetObject属性可以用来存储一些附加信息,但我看不出有什么方法可以在throw语句之前向该属性添加内容,因为该属性是ReadOnly,我认为该属性不是用来存储附加用户数据的。

虽然System.Management.Automation.ErrorRecord类在技术上没有密封,文档中也没有提到子类化,但看起来实际上不支持子类化ErrorRecord:

正如您所经历的,throw的原始SqlRequestException实例并没有在调用堆栈中这样,可能是,因为需要复制到基类的实例中。

改为子类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

您可以在catch块中创建Custom对象(您不需要自己的类(,类似这样。

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

更多关于创建自定义对象自定义对象

我曾经做过类似的事情。

首先,我必须将我的函数转换为Cmdlet,以便访问$PSCmdlet.ThrowTerminatingError并构建自己的[system.management.automation.errorrecord]

呼叫方在CCD_ 27块中具有CCD_。如果需要内部细节,可以通过$PSItem.Exception.ComplementaryInfo$PSItem.Exception.ErrorRecord访问

根据您的问题,它看起来像下面的代码。但是如果呼叫者的catch块只能是Write-Log -Text $_,这将没有帮助。

class myException: system.exception
{
[System.Management.Automation.ErrorRecord]$ErrorRecord
$ComplementaryData
myException(
[System.Management.Automation.ErrorRecord]$ErrorRecord,
$ComplementaryData
) : base($errorRecord.Exception.message,$errorRecord.exception)
{
$this.ErrorRecord       = $ErrorRecord
$this.ComplementaryData = $ComplementaryData
}
}
function doSomething {
[CmdletBinding()]
param( )
try
{
[int]::Parse('not a number') # Sample exception.
}
catch
{
$PSCmdlet.ThrowTerminatingError(
[system.management.automation.errorrecord]::new(
[myException]::new($PSItem,'some more data'),
$PSItem.FullyQualifiedErrorId,
$PSItem.CategoryInfo.Category,
$PSItem.TargetObject
)
)
}
}

# caller's code
try
{ 
DoSomething
}
catch
{
Write-Host -ForegroundColor Red $_ # to simulate Write-Log -Text $_
# you can access your complementary data + info from the original ErrorRecord
$PSItem.Exception.ComplementaryData
$PSItem.Exception.ErrorRecord.InvocationInfo
$PSItem.Exception.ErrorRecord.ScriptTrace
}

最新更新