WinFormsアプリケーションですべての「未処理」例外をキャッチするものを作成するにはどうすればよいですか?


85

今まで、私はちょうど周りtry / catchブロックを置くApplication.RunProgram.csプログラムへのエントリポイント。これにより、デバッグモードですべての例外が十分にキャッチされますが、デバッグモードなしでプログラムを実行すると、例外が処理されなくなります。未処理の例外ボックスが表示されます。

私はこれが起こらないようにしたい。非デバッグモードで実行しているときにすべての例外をキャッチしたい。プログラムには複数のスレッドがあり、それらからのすべての例外が同じハンドラーによってキャッチされることが望ましい。DBに例外を記録したい。誰かがこれを行う方法について何かアドバイスがありますか?

回答:


110

ThreadExceptionドキュメントの例を見てください。

public static void Main(string[] args)
{
   // Add the event handler for handling UI thread exceptions to the event.
    Application.ThreadException += new     
  ThreadExceptionEventHandler(ErrorHandlerForm.Form1_UIThreadException);

  // Set the unhandled exception mode to force all Windows Forms errors
  // to go through our handler.
  Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);

  // Add the event handler for handling non-UI thread exceptions to the event. 
  AppDomain.CurrentDomain.UnhandledException += new       
  UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
}

また、デバッグが容易になるため、デバッグ時に例外をキャッチしないようにすることもできます。それはややハックですが、そのために上記のコードをラップすることができます

 if (!AppDomain.CurrentDomain.FriendlyName.EndsWith("vshost.exe")) { ... }

デバッグ時に例外がキャッチされないようにするため。


1
バックグラウンドワーカーを作成しましたが、doworkイベントハンドラーで意図的にnull参照例外が発生しました。ただし、次のように設定しているにもかかわらず、AppDomain.CurrentDomain.UnhandledExceptionによってキャッチされませんでした。Application.ThreadException+ = new System.Threading.ThreadExceptionEventHandler(Application_ThreadException); Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException); AppDomain.CurrentDomain.UnhandledException + = new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
Isaac Bolinger 2011

4
@IsaacB、バックグラウンドワーカーは例外自体をキャッチします。RunCompletedEventArgs.Errorプロパティを確認しても、RunWorkerCompletedで例外を確認できます。
Can Gencer 2011

1
これをメインフォームのOnLoadに配置することで、追加のスレッドの例外処理をテストできます。new Thread(()=> {throw new Exception();})。Start();
Can Gencer 2011

残念ながら、UnhandledExceptionを処理しても、アプリケーションの終了は停止しません:(
Nazar Grynko 2013

7
FriendlyName.EndsWithハックの代わりに、よりクリーンなDebugger.IsAttachedを試してください。
溶融形態2016年

27

NET 4では、特定の例外がデフォルトでキャッチされなくなりました。これらは、AccessViolationExceptionなど、実行可能ファイルの(おそらく致命的な)破損状態を示す例外になる傾向があります。

メインメソッドの前で[HandleProcessCorruptedStateExceptions]タグを使用してみてください。

using System.Runtime.ExceptionServices.HandleProcessCorruptedStateExceptions

[HandleProcessCorruptedStateExceptions]
public static int Main()
{
    try
    {
        // Catch any exceptions leaking out of the program
        CallMainProgramLoop();
    }
    catch (Exception e) // We could be catching anything here
    {
        System.Console.WriteLine(e.Message);
        return 1;
    }
    return 0;
  } 

タグ付きAppDomain.CurrentDomain.UnhandledExceptionApplication.ThreadExceptionも使用できます[HandleProcessCorruptedStateExceptions]か?
キケネット2017年

18

良い例はhttp://www.csharp-examples.net/catching-unhandled-exceptions/にあります。 基本的に、メインを次のように変更します。

static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);

        Application.ThreadException += new ThreadExceptionEventHandler(Application_ThreadException);
        Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
        AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);

        Application.Run(new Form1());
    }

    static void Application_ThreadException(object sender, ThreadExceptionEventArgs e)
    {
        MessageBox.Show(e.Exception.Message, "Unhandled Thread Exception");
    }

    static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
    {
        MessageBox.Show((e.ExceptionObject as Exception).Message, "Unhandled UI Exception");
    }

9

そのためにNBugライブラリを使用できます。このような最小限のセットアップで:

NBug.Settings.Destination1 = "Type=Mail;From=me@mycompany.com;To=bugtracker@mycompany.com;SmtpServer=smtp.mycompany.com;";
AppDomain.CurrentDomain.UnhandledException += NBug.Handler.UnhandledException;
Application.ThreadException += NBug.Handler.ThreadException;

アプリケーションがクライアントにデプロイされている場合でも、アプリケーション内の未処理のすべてのバグに関する情報の収集を開始できます。サードパーティのライブラリを使用したくない場合は、以下のイベントに添付する必要があります。

// These two should come before enabling visual styles or running the application
AppDomain.CurrentDomain.UnhandledException += ...
Application.ThreadException += ...
...
Application.Run(new Form1());

1
どういたしまして。さらに質問がある場合は、NBugプロジェクトディスカッションフォーラム(nbusy.com/forum/f11)を使用するか、ここで[nbug]タグを使用してください。
Teoman Soygul 2011

もちろん、「通常の」イベントハンドラーをUnhandledExceptionイベントにサブスクライブすることもできます。msdn.microsoft.com/en-us/library/…を
neo2862 2011

Win7 + VS10の皆さん、これらのイベントをサブスクライブすると、サブスクリプションは実行されず、代わりに通常のWindows Vista / 7ダイアログが表示されます。Check Online for a SolutionまたはClose the Programなど。ただし、サブスクライブしないと、通常の一般的な.NET未処理例外が発生します。窓。これは、リリースビルドとデバッグビルドの両方で発生します。また、[Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);何も変更しない]を設定してみました。
ギデオン2011

@giddy、例外を処理した後、Environment.Exit(1);を使用してアプリケーションを終了する必要があります。エラーウィンドウを表示したくない場合。
Teoman Soygul 2011

@Teoお返事ありがとうございます。自分のエラーフォームを表示してから、アプリを終了したい。ただし、イベントサブスクリプションは実行されず、例外が発生したときに一般的なWin Vista / 7ダイアログが表示されるだけです。しかし、サブスクライブしないと、一般的な.NETの未処理の例外ダイアログが表示されます。
ギデオン2011
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.