在.NET中读取本机win32异常数据/参数

时间:2014-09-03 17:44:15

标签: c# c++ exception pinvoke seh

我正在尝试接收有关我在托管(.net / c#)的catch块中抛出本机(c ++ / win32)的异常的数据。

例如,在c ++中,我们可以:

void MyFunc()
{
    const char* data = "my exception info";
    ULONG_PTR args[1] { data };
    RaiseException(0,0,1,args);
}

可以通过c#:

中的P / Invoke调用此函数
[DLLImport("MyLib.dll")]
extern public static void MyFunc();

static void Main()
{
    try { MyFunc(); }
    catch(SEHException seh)
    {
        // Where is my exception info? :(
    }
}

SEHException不包含导入的DLL函数中的字符串。

SEHException.ErrorCode似乎总是E_FAIL,但我想在任何情况下编组比int更丰富的数据。

我是否遗漏了某些内容,或者是否有另一种方法可以通过异常恢复此字符串数据?

目的是通过使用SetUnhandledExceptionFilter,FYI设置本机过滤器,使用本机堆栈跟踪重新引发本机异常。

1 个答案:

答案 0 :(得分:2)

SEH异常通常没有参数,而且数据方式也很少。您真正得到的只有numeric exception codethe processor state when the exception happened (including the instruction pointer and stack pointer)

C ++异常处理使用的是用于启动处理程序的SEH异常,但C ++异常对象实际存储在别处(详细信息是编译器及其运行时库的内部)。从另一种语言访问它几乎是不可能的;甚至其他C ++编译器都有一段糟糕的时间。所有C ++异常共享一个异常代码。

与您一样,手动调用RaiseException确实允许您存储异常参数,就像操作系统异常EXCEPTION_ACCESS_VIOLATIONEXCEPTION_IN_PAGE_ERROR一样,请参阅EXCEPTION_RECORD on MSDN。使用Microsoft C ++编译器,您可以通过GetExceptionInformation访问它们。而且你肯定不应该将std::string之类的C ++对象与RaiseException结合起来 - 你错过了C ++编译器为这些对象的生命周期管理添加的额外魔力。将字符串数据作为const char*传递给字符串文字应该没问题,但是..

然后您遇到了在.NET中检索此信息的问题。即使是这种有限的(异常代码,上下文和记录,没有C ++对象)信息,我认为你不能从.NET SEHException对象获得。您看到E_FAIL的原因是文档中此注释的结果,而不是异常代码。

  

SEHException类处理从非托管代码抛出但尚未映射到另一个.NET Framework异常的SEH错误。 SEHException类还响应HRESULT E_FAIL,其值为0x80004005。