Окончательный управляемый обработчик исключений в смешанном собственном / управляемом исполняемом файле?
-
08-06-2019 - |
Вопрос
У меня есть приложение MFC, скомпилированное с помощью / clr, и я пытаюсь реализовать окончательный обработчик для управляемых исключений, которые в противном случае не были бы перехвачены.Для собственных исключений переопределение CWinApp::ProcessWndProcException
работает.
Два события, предложенные в книге Джеффа Статья CodeProject,Application.ThreadException
и AppDomain.CurrentDomain.UnhandledException
, не повышаются.
Кто-нибудь может предложить способ предоставить окончательный управляемый обработчик исключений для смешанного исполняемого файла?
Обновить:
Похоже, что эти обработчики исключений запускаются только после Application.Run
или что-то подобное (есть разновидность рабочего потока, не могу вспомнить название.) Если вы хотите действительно глобально перехватывать управляемое исключение, вам нужно установить фильтр SEH.Ты не собираешься получать System.Exception
и если вам нужен callstack, вам придется создать свой собственный walker.
В вопросе форума MSDN по этой теме было предложено переопределить достаточно низкоуровневую точку основного потока MFC в try ... catch (Exception^)
.Например, CWinApp::Run
.Это может быть хорошим решением, но я не рассматривал какие-либо последствия для производительности или стабильности.У вас будет возможность войти в систему с помощью стека вызовов, прежде чем вы выйдете из системы, и вы сможете избежать поведения Windows unahndled exception по умолчанию.
Решение
Ознакомившись с Интернетом, вы обнаружите, что вам нужно установить фильтр, чтобы получать неуправляемые исключения, проходящие фильтры по пути в ваш домен приложения.От CLR и фильтры необработанных исключений:
Среда CLR использует механизм фильтрации необработанных исключений SEH для перехвата необработанных исключений.
Другие советы
Использование этих двух обработчиков исключений должно сработать.
Почему "должен"?
События не вызываются с помощью приведенного ниже:
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;
}
Использование этих двух обработчиков исключений должно сработать.Вы уверены, что добавили их в то место, где они будут вызываться и правильно установлены (т. Е. в вашем приложении управляемый точка входа - ты ведь ее вставил, верно?)