.NET 1.1の未処理例外ハンドラー
-
08-06-2019 - |
質問
私は .NET 1.1 アプリケーションを保守しています。私が課せられた任務の 1 つは、ユーザーに不親切なエラー通知が表示されないようにすることです。
ハンドラーを追加しました Application.ThreadException
そして AppDomain.CurrentDomain.UnhandledException
, 、呼び出されます。私の問題は、標準の CLR エラー ダイアログが (例外ハンドラーが呼び出される前に) 表示されたままであることです。
ジェフはブログでこの問題について語っています ここ そして ここ. 。しかし、解決策はありません。では、キャッチされなかった例外を処理し、わかりやすいダイアログ ボックスを表示する .NET 1.1 の標準的な方法は何でしょうか?
Jeff の応答は、彼が提供したリンクに、必要なことを行う方法についての最も完全な情報が含まれているため、正解としてマークされました。
解決
ああ、Windows フォームでは間違いなく動作させることができるはずです。注意しなければならない唯一のことは、別のスレッドで問題が発生していることです。
ここに古いコード プロジェクトの記事がありますので、参考にしてください。
他のヒント
AppDomain.UnhandledException です イベント, 、グローバル例外ハンドラーではありません。これは、このエラーが発生するまでに、アプリケーションはすでに排水溝に落ち始めており、クリーンアップとエラー ログを実行する以外にできることは何もないことを意味します。
舞台裏で何が起こったかは次のとおりです。フレームワークは例外を検出し、呼び出しスタックを最上位までたどりましたが、エラーから回復するハンドラーが見つからなかったため、実行を継続しても安全かどうかを判断できませんでした。そこで、シャットダウン シーケンスが開始され、既に運命にあるプロセスに敬意を表できるよう、礼儀としてこのイベントが開始されました。これは、例外がメインスレッドで処理されないままになっている場合に発生します。
この種のエラーに対する単一点の解決策はありません。このエラーが発生するすべての場所の上流に実際の例外ハンドラー (catch ブロック) を配置し、それを (たとえば) 単に報告して続行しても安全かどうかを判断するグローバル ハンドラー メソッド/クラスに転送する必要があります。例外のタイプおよび/または内容。
編集:Windows に組み込まれているエラー報告メカニズムを無効にする (= ハックする) ことで、アプリがダウンしたときに必須の「クラッシュと書き込み」ダイアログが表示されないようにすることができます。ただし、これが有効になるのは、 全て 自分のアプリケーションだけでなく、システム内のアプリケーションも含めることができます。
.NET 1.x Windows Forms アプリケーションの未処理例外の動作は、以下に依存します。
- 例外をスローしたスレッドのタイプ
- ウィンドウメッセージの処理中に発生したかどうか
- デバッガーがプロセスにアタッチされているかどうか
- DbgJitDebugLaunchSetting レジストリ設定
- App.Config の jitDebugging フラグ
- Windows フォーム例外ハンドラーをオーバーライドしたかどうか
- CLR の例外イベントを処理したかどうか
- 月の満ち欠け
未処理の例外のデフォルトの動作は次のとおりです。
- ウィンドウ メッセージをポンピングするときにメイン スレッドで例外が発生した場合、その例外は Windows フォーム例外ハンドラーによってインターセプトされます。
- ウィンドウ メッセージをポンピングするときにメイン スレッドで例外が発生した場合、Windows フォーム例外ハンドラーによってインターセプトされない限り、アプリ プロセスは終了します。
- 例外が手動、スレッドプール、またはファイナライザー スレッドで発生した場合、その例外は CLR によって飲み込まれます。
未処理の例外の連絡先は次のとおりです。
- Windows フォーム例外ハンドラー。
- JIT デバッグ レジストリ スイッチ DbgJitDebugLaunchSetting。
- CLR の未処理例外イベント。
Windows フォームの組み込み例外処理は、デフォルトで次の処理を行います。
- 次の場合に未処理の例外をキャッチします。
- 例外はメインスレッド上にあり、デバッガは接続されていません。
- ウィンドウメッセージの処理中に例外が発生します。
- App.Config の jitDebugging = false。
- ユーザーにダイアログを表示し、アプリの終了を防ぎます。
後者の動作を無効にするには、App.Config で jitDebugging = true を設定します。ただし、これがアプリの終了を停止する最後のチャンスになる可能性があることに注意してください。したがって、ハンドルされない例外をキャッチする次のステップは、イベント Application.ThreadException を登録することです。例:
Application.ThreadException += new
Threading.ThreadExceptionHandler(CatchFormsExceptions);
HKEY_LOCAL_MACHINE\Software.NetFramework にあるレジストリ設定 DbgJitDebugLaunchSetting に注目してください。これには、私が知っている次の 3 つの値のいずれかがあります。
- 0:「デバッグまたは終了」を尋ねるユーザー ダイアログを示します。
- 1:CLR が処理できるように例外を通過させます。
- 2:DbgManagedDebugger レジストリ キーで指定されたデバッガを起動します。
Visual Studio で、メニューに移動します ツール → オプション → デバッグ → ジット をクリックして、このキーを 0 または 2 に設定します。ただし、エンドユーザーのマシンでは通常、値 1 が最適です。このレジストリ キーは、CLR 未処理例外イベントが発生する前に処理されることに注意してください。
この最後のイベントは、未処理の例外をログに記録する最後のチャンスです。これは、Finally ブロックが実行される前にトリガーされます。このイベントは次のようにインターセプトできます。
AppDomain.CurrentDomain.UnhandledException += new
System.UnhandledExceptionEventHandler(CatchClrExceptions);
これはコンソール アプリケーションですか、それとも Windows フォーム アプリケーションですか?.NET 1.1 コンソール アプリケーションの場合、これは残念ながら仕様です。MSFT 開発者によって確認されています。 あなたが参照した 2 番目のブログ投稿:
ところで、私の 1.1 マシンでは、MSDN の例では期待どおりの出力が得られます。2 行目は、デバッガーを接続する (または接続しない) まで表示されないだけです。v2 では、デバッガがアタッチされる前に UnhandledException イベントが発生するように、状況を逆転させました。これは、ほとんどの人が期待していることと思われます。
.NET 2.0 の方がこれがうまくできるように思えますが (ありがたいことに)、正直に言って、戻って確認する時間がありませんでした。
Windows フォーム アプリケーションです。Application.ThreadException によってキャッチされる例外は正常に動作し、醜い .NET 例外ボックスは表示されません (わかりました 終了します、 キャンセル デバッグするには?誰がそれを思いついたのですか??)。
これによってキャッチされない例外がいくつか発生し、最終的に AppDomain.UnhandledException イベントが発生して問題が発生していました。これらの例外のほとんどは捕捉できたと思います。現在は、それらを素晴らしいエラー ボックスに表示しています。
したがって、Application.ThreadException ハンドラーによって例外がキャッチされないような状況が他にないことを祈る必要があります。