10

私は本番デバッグ機能を強化するプロジェクトに取り組んでいます。私たちの目標は、例外が管理されているか管理されていないか、および管理されているスレッドと管理されていないスレッドのどちらで発生するかを問わず、未処理の例外に対して確実にミニダンプを生成することです。

現在、これには優れたClrDumpライブラリを使用していますが、必要な機能が正確に提供されていないため、例外フィルタリングの背後にあるメカニズムを理解したいので、これを自分で試してみました。

私はこのブログ記事に従ってSEHハンドラーを自分でインストールすることから始めました:http: //blogs.microsoft.co.il/blogs/sasha/archive/2007/12.aspx。この手法はコンソールアプリケーションで機能しますが、WinFormsアプリケーションから同じことを試してみると、さまざまな管理されていない例外に対してフィルターが呼び出されません。

ClrDumpは、私が行っていないことを何をすることができますか?ClrDumpはすべての場合にダンプを生成するため、その例外フィルターを呼び出す必要があります...

注:私はADPlusの機能を認識しており、AeDebugレジストリキーの使用も検討しました...これらも可能ですが、トレードオフもあります。

ありがとう、デイブ

// Code adapted from <http://blogs.microsoft.co.il/blogs/sasha/archive/2007/12.aspx>
LONG WINAPI MyExceptionFilter(__in struct _EXCEPTION_POINTERS *ExceptionInfo)
{
   printf("Native exception filter: %X\n",ExceptionInfo->ExceptionRecord->ExceptionCode);

   Beep(1000,1000);
   Sleep(500);
   Beep(1000,1000);

   if(oldFilter_ == NULL)
   {
      return EXCEPTION_CONTINUE_SEARCH;
   }

   LONG ret = oldFilter_(ExceptionInfo);
   printf("Other handler returned %d\n",ret);

   return ret;
}



#pragma managed

namespace SEHInstaller
{
   public ref class SEHInstall
   {
   public:
      static void InstallHandler()
      {    
         oldFilter_ = SetUnhandledExceptionFilter(MyExceptionFilter);
         printf("Installed handler old=%x\n",oldFilter_);
      }


   };
}
4

3 に答える 3

9

Windows フォームには、既定で次のことを行う組み込みの例外ハンドラーがあります。

  • 次の場合に、未処理のマネージ例外をキャッチします。
    • デバッガーが接続されていない。
    • ウィンドウ メッセージの処理中に例外が発生し、
    • App.Config で jitDebugging = false。
  • ユーザーにダイアログを表示し、アプリの終了を防ぎます。

App.Config でjitDebugging = trueを設定することにより、最初の動作を無効にすることができます。これは、アプリの終了を停止する最後のチャンスは、イベント Application.ThreadException に登録して未処理の例外をキャッチすることです (例: C#)。

Application.ThreadException += new Threading.ThreadExceptionHandler(CatchFormsExceptions);

ここで未処理の例外をキャッチしないことにした場合は、HKLM\Software.NetFramework の下のレジストリ設定DbgJitDebugLaunchSettingを確認または変更する必要があります。これには、私が認識している 3 つの値のいずれかがあります。

  • 0: 「デバッグまたは終了」を求めるユーザー ダイアログを表示します。
  • 1: CLR が処理できるように例外を通過させます。
  • 2: DbgManagedDebugger レジストリ キーで指定されたデバッガーを起動します。

In Visual Studio, go to Tools>Options>Debugging>JIT to set this key to 0 or 2. ただし、通常、エンド ユーザーのマシンでは値 1 が必要です。このレジストリ キーは、説明する CLR 未処理の例外イベントの前に実行されることに注意してください。

次に、説明したネイティブ例外フィルターを設定できます。

于 2008-10-26T17:55:01.577 に答える
4

GUI スレッドの例外を非 GUI のものと同じように機能させて、同じ方法で処理されるようにする場合は、次のようにします。

Application.SetUnhandledExceptionMode(UnhandledExceptionMode.ThrowException);

背景は次のとおりです。

マネージド GUI アプリでは、デフォルトで、GUI スレッドで発生した例外は、次のようにカスタマイズできる Application.ThreadException に割り当てられたものによって処理されます。

Application.ThreadException += 
    new System.Threading.ThreadExceptionEventHandler(Application_ThreadException);

他のスレッドで発生した例外は、次のようにカスタマイズできる AppDomain.CurrentDomain.UnhandledException によって処理されます。

AppDomain.CurrentDomain.UnhandledException += 
    new UnhandledExceptionEventHandler(Program.CurrentDomain_UnhandledException);

UnHandledException への割り当ては、Win32 SetUnhandledExceptionFilter の呼び出しとまったく同じように機能します。

ミニダンプを作成して使用することが目的の場合は、Windows 用デバッグ ツール sos.dll を使用する必要があります。ミニダンプ MiniDumpWithFullMemory を生成する必要があります。

そして、それでも、おそらくあなたが望むすべてのものを手に入れることはできません. System.Diagnostics.StackTrace を使用して、コール マネージド コール スタックを取得します。

于 2009-09-26T18:15:43.100 に答える
2

SetUnhandledExceptionFilter は、Win32 例外が処理されずにスレッド コールスタックの先頭に達したときに呼び出されるハンドラーをインストールします。

マネージを含む多くの言語ランタイムでは、言語例外は Win32 例外を使用して実装されます。ただし、マネージ ランタイムには、各スレッドの先頭にトップ レベルの __try __catch(...) ブロックがあり、win32 からランタイムへの例外をキャッチし、それらを Win32 のトップ レベル ハンドラにエスケープさせずに処理します。

例外が Win32 の TheadProc ハンドラーにエスケープすることは決して許可されないため、このレベルでハンドラーを挿入するには、特定のランタイムの知識が必要です。

于 2008-10-24T14:22:30.627 に答える