混合本机/托管可执行文件中的最终托管异常处理程序?

发布于 2024-07-04 04:04:09 字数 809 浏览 8 评论 0原文

我有一个使用 /clr 编译的 MFC 应用程序,并且我正在尝试为未捕获的托管异常实现最终处理程序。 对于本机异常,重写 CWinApp::ProcessWndProcException 是可行的。

Jeff 的 CodeProject 文章 中建议的两个事件,Application.ThreadException< /code> 和 AppDomain.CurrentDomain.UnhandledException 不会引发。

任何人都可以建议一种为混合可执行文件提供最终托管异常处理程序的方法吗?


更新:

看来这些异常处理程序仅在 Application.Run 或类似的下游触发(有工作线程风格,不记得名称。)如果您想真正全局捕获托管异常您确实需要安装 SEH 过滤器。 您不会遇到 System.Exception,如果您想要调用堆栈,则必须滚动自己的 Walker。

在关于此主题的 MSDN 论坛问题中,建议在 try ... catch (Exception^) 中覆盖主 MFC 线程的足够低级别的点。 例如,CWinApp::Run。 这可能是一个很好的解决方案,但我还没有考虑任何性能或稳定性影响。 在退出之前,您将有机会使用调用堆栈进行日志记录,并且可以避免默认的 Windows 未处理的异常行为。

I have an MFC application compiled with /clr and I'm trying to implement a final handler for otherwise un-caught managed exceptions. For native exceptions, overriding CWinApp::ProcessWndProcException works.

The two events suggested in Jeff's CodeProject article,Application.ThreadException and AppDomain.CurrentDomain.UnhandledException, are not raised.

Can anyone suggest a way to provide a final managed exception handler for a mixed executable?


Update:

It appears that these exception handlers are only triggered downstream of Application.Run or similar (there's a worker thread flavor, can't remember the name.) If you want to truly globally catch a managed exception you do need to install an SEH filter. You're not going to get a System.Exception and if you want a callstack you're going to have to roll your own walker.

In an MSDN forum question on this topic it was suggested to override a sufficiently low-level point of the main MFC thread in a try ... catch (Exception^). For instance, CWinApp::Run. This may be a good solution but I haven't looked at any perf or stability implications. You'll get a chance to log with a call stack before you bail and you can avoid the default windows unahndled exception behavior.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

雨轻弹 2024-07-11 04:04:10

使用这两个异常处理程序应该可以工作。

为什么要?”

使用以下内容不会引发事件:

extern "C" void wWinMainCRTStartup();

// managed entry point
[System::STAThread]
int managedEntry( void )
{
    FinalExceptionHandler^ handler = gcnew FinalExceptionHandler();

    Application::ThreadException += gcnew System::Threading::ThreadExceptionEventHandler(
                                        handler,
                                        &FinalExceptionHandler::OnThreadException);

    AppDomain::CurrentDomain->UnhandledException += gcnew UnhandledExceptionEventHandler(
                                                        handler,
                                                        &FinalExceptionHandler::OnAppDomainException);

    wWinMainCRTStartup();

    return 0;
}

// final thread exception handler implementation
void FinalExceptionHandler::OnThreadException( Object^ /* sender */, System::Threading::ThreadExceptionEventArgs^ t )
{
    LogWrapper::log->Error( "Unhandled managed thread exception.", t->Exception );
}

// final appdomain exception handler implementation
void FinalExceptionHandler::OnAppDomainException(System::Object ^, UnhandledExceptionEventArgs ^args)
{
    LogWrapper::log->Error( "Unhandled managed appdomain exception.", (Exception^)(args->ExceptionObject) );
}

BOOL CMyApp::InitInstance()
{
    throw gcnew Exception("test unhandled");
    return TRUE;
}

Using those two exception handlers should work.

Why "should?"

The events are not raised using the below:

extern "C" void wWinMainCRTStartup();

// managed entry point
[System::STAThread]
int managedEntry( void )
{
    FinalExceptionHandler^ handler = gcnew FinalExceptionHandler();

    Application::ThreadException += gcnew System::Threading::ThreadExceptionEventHandler(
                                        handler,
                                        &FinalExceptionHandler::OnThreadException);

    AppDomain::CurrentDomain->UnhandledException += gcnew UnhandledExceptionEventHandler(
                                                        handler,
                                                        &FinalExceptionHandler::OnAppDomainException);

    wWinMainCRTStartup();

    return 0;
}

// final thread exception handler implementation
void FinalExceptionHandler::OnThreadException( Object^ /* sender */, System::Threading::ThreadExceptionEventArgs^ t )
{
    LogWrapper::log->Error( "Unhandled managed thread exception.", t->Exception );
}

// final appdomain exception handler implementation
void FinalExceptionHandler::OnAppDomainException(System::Object ^, UnhandledExceptionEventArgs ^args)
{
    LogWrapper::log->Error( "Unhandled managed appdomain exception.", (Exception^)(args->ExceptionObject) );
}

BOOL CMyApp::InitInstance()
{
    throw gcnew Exception("test unhandled");
    return TRUE;
}
暗地喜欢 2024-07-11 04:04:10

使用这两个异常处理程序应该可以工作。 您确定已将它们添加到将被调用并正确设置的位置(即,在应用程序的托管入口点中 - 您确实添加了一个,对吗?)

Using those two exception handlers should work. Are you sure you've added them in a place where they're going to be called and properly set (ie, in your application's managed entry point -- you did put one in, right?)

只有影子陪我不离不弃 2024-07-11 04:04:09

浏览一下互联网,您会发现您需要安装一个过滤器,以使非托管异常通过过滤器到达您的 AppDomain。 来自 CLR和未处理的异常过滤器

CLR 依赖 SEH 未处理异常过滤机制来捕获未处理异常。

Taking a look around the internets, you'll find that you need to install a filter to get the unmanaged exceptions passing the filters on their way to your AppDomain. From CLR and Unhandled Exception Filters:

The CLR relies on the SEH unhandled exception filter mechanism to catch unhandled exceptions.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文