ネイティブ/マネージド実行可能ファイルが混在した最終マネージド例外ハンドラー?
-
08-06-2019 - |
質問
/clr を使用してコンパイルされた MFC アプリケーションがあり、他の方法ではキャッチされなかったマネージ例外用の最終ハンドラーを実装しようとしています。ネイティブ例外の場合、オーバーライド CWinApp::ProcessWndProcException
動作します。
Jeff の記事で提案された 2 つのイベント コードプロジェクトの記事,Application.ThreadException
そして AppDomain.CurrentDomain.UnhandledException
, 、上げられません。
混合実行可能ファイルに最終マネージ例外ハンドラーを提供する方法を誰かが提案できますか?
アップデート:
これらの例外ハンドラーは、下流でのみトリガーされるようです。 Application.Run
または同様のもの (ワーカー スレッド フレーバーがありますが、名前は思い出せません。) マネージド例外を真にグローバルにキャッチしたい場合は、SEH フィルターをインストールする必要があります。あなたは得するつもりはありません System.Exception
コールスタックが必要な場合は、独自のウォーカーをロールする必要があります。
このトピックに関する MSDN フォーラムの質問では、メイン MFC スレッドの十分に低レベルのポイントをオーバーライドすることが提案されました。 try ... catch (Exception^)
. 。例えば、 CWinApp::Run
. 。これは良い解決策かもしれませんが、パフォーマンスや安定性への影響についてはまだ調べていません。保釈する前にコールスタックでログを記録する機会が得られ、Windows のデフォルトのハンドルされない例外動作を回避できます。
解決
インターネットを見回してみると、AppDomain に到達する途中でフィルターを通過するアンマネージ例外を取得するには、フィルターをインストールする必要があることがわかります。から CLR および未処理例外フィルター:
CLR は、SEH 未処理例外フィルター メカニズムに依存して、未処理例外をキャッチします。
他のヒント
これら 2 つの例外ハンドラーを使用すると機能するはずです。
どうして〜しなきゃいけない?"
イベントは以下を使用して発生させません。
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;
}
これら 2 つの例外ハンドラーを使用すると機能するはずです。それらが呼び出されて適切に設定される場所 (つまり、アプリケーションの 管理された エントリ ポイント -- 入れましたよね?)