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.
Enable mixed-mode debugging for a native calling appIn the <Project> Property Pages dialog box, expand Configuration Properties, and then select Debugging. Set Debugger Type to Mixed or Auto. Select OK.
Exception handling in C++ consists of three keywords: try, throw and catch: The try statement allows you to define a block of code to be tested for errors while it is being executed. The throw keyword throws an exception when a problem is detected, which lets us create a custom error.
The Environmental Health Support Center (EHSC) supports the IHS Office of Environmental Health and Engineering by providing training and resources on a wide variety of subjects including, but not limited to: Leadership and Personal Development (LPD)
To catch and delete exceptionsUse the try keyword to set up a try block. Execute any program statements that might throw an exception within a try block. Use the catch keyword to set up a catch block. Place exception-handling code in a catch block.
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.
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;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With