我正在尝试接收有关我在托管(.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设置本机过滤器,使用本机堆栈跟踪重新引发本机异常。
答案 0 :(得分:2)
SEH异常通常没有参数,而且数据方式也很少。您真正得到的只有numeric exception code和the processor state when the exception happened (including the instruction pointer and stack pointer)。
C ++异常处理使用的是用于启动处理程序的SEH异常,但C ++异常对象实际存储在别处(详细信息是编译器及其运行时库的内部)。从另一种语言访问它几乎是不可能的;甚至其他C ++编译器都有一段糟糕的时间。所有C ++异常共享一个异常代码。
与您一样,手动调用RaiseException
确实允许您存储异常参数,就像操作系统异常EXCEPTION_ACCESS_VIOLATION
和EXCEPTION_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。