Question

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.

Was it helpful?

Solution

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.

OTHER TIPS

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;
}

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?)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top