不良フレームを修正する方法
捕捉されなかった例外がスローされたことを知る: .NET Tips: C#, VB.NET
ここでは、Try...Catch...で捕捉(キャッチ、ハンドル、トラップ)されなかった例外(エラー)がスローされたときに、その例外の情報を知るための方法を紹介します。
Application.ThreadExceptionイベントを使用する方法
Windows Forms アプリケーションでは、捕捉されなかった例外がスローされるとApplication.ThreadExceptionイベントが発生します。
以下に例を示します。ここではフォームのLoadイベントハンドラでThreadExceptionイベントハンドラを追加していますが、実際には、エントリポイントの適当な位置(Application.Runメソッドを呼び出す前)に記述したほうがよいでしょう。エントリポイントについて詳しくは、こちらをご覧ください。
照合と非丁の違いは何ですか?Private Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs) _ Handles MyBase.Load AddHandler Application.ThreadException, _ AddressOf Application_ThreadException End Sub Public Sub Application_ThreadException(ByVal sender As Object, _ ByVal e As System.Threading.ThreadExceptionEventArgs) Try MessageBox.Show(e.Exception.Message, "エラー") Finally Application.Exit() End Try End Sub
private void Form1_Load(object sender, EventArgs e) { Application.ThreadException += new System.Threading.ThreadExceptionEventHandler( Application_ThreadException); } private void Application_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e) { try { MessageBox.Show(e.Exception.Message, "エラー"); } finally { Application.Exit(); } } private void Button1_Click(object sender, EventArgs e) { throw new ApplicationException("テストです。"); }
上記のコードを実行すると、Button1がクリックされて例外がスローされたときにメッセージボックスにメッセージが表示されて(「テストです。」と表示される)、アプリケーションが終了します。
ThreadExceptionイベントハンドラでは、通常、次のような処理を行います。
- ユーザーにエラーが発生したことを伝える。
- 必要ならば、例外情報をログに保存する。
- 可能ならば、アプリケーション終了時の処理(設定の保存など)を行う。
- アプリケーションを終了する。
ThreadExceptionイベントを使う場合は、次のような点に注意する必要があります。
ビデオから音声を分離する方法- Windows Forms アプリケーションでのみ使用できます。
- このイベントが発生するのは、メインスレッドで例外がスローされた時のみです。
- 上記のコードをVisual Studioの「デバッグ開始」で実行したときは、ThreadExceptionイベントが発生せずに、デバッガのダイアログが表示されます。Visual Studio 2003以前では、Application.Runメソッドを呼び出す前(フォームのインスタンスを作成する前)にThreadExceptionイベントハンドラを追加することにより、ThreadExceptionイベントが発生するようになります。2005では、こうしても解決されません(解決されるという場合もあるようです)。デバッガダイアログを表示せずにThreadExceptionイベントを確認するには、メニューの「デバッグ」-「デバッグなしで開始」で実行します。
- ThreadExceptionイベントハンドラ内でアプリケーションを終了させるコードを記述しないとアプリケーションは終了しません。
- サポート技術情報 KB915322によると、.NET Framework 1.1 SP1でApplication.ThreadExceptionイベントが発生しないケースがあるようです。
- .NET Framework 2.0以降では、Application.SetUnhandledExceptionModeメソッドにより、アプリケーション構成ファイルに関係なく、常にThreadExceptionを発生されるか(CatchExceptionを指定)、あるいはさせないか(ThrowExceptionを指定)を設定することができます。SetUnhandledExceptionModeメソッドは、Application.Runの前に呼び出します。
補足:SetUnhandledExceptionModeメソッドは、2番目のパラメータにFalseを指定することにより、アプリケーション例外モードとすることができるようです(デフォルトは、スレッド例外モード)。しかし現在は、SetUnhandledExceptionModeメソッドの2番目のパラメータをFalseにして呼び出すと、例外がスローされます。
AppDomain.UnhandledExceptionイベントを使用する方法
AppDomain.UnhandledExceptionイベントによっても捕捉されていない例外を調べることができます。
以下に例を示します。Application.ThreadExceptionイベントの例をUnhandledExceptionイベント用に書き換えただけです。こちらもやはりUnhandledExceptionイベントハンドラを追加するコードをエントリポイントに記述したほうがよいでしょう。
Napsterのファイルを焼く方法Private Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs) _ Handles MyBase.Load AddHandler System.AppDomain.CurrentDomain.UnhandledException, _ AddressOf CurrentDomain_UnhandledException End Sub Private Sub CurrentDomain_UnhandledException(ByVal sender As Object, _ ByVal e As UnhandledExceptionEventArgs) Try Dim ex As Exception = CType(e.ExceptionObject, Exception) MessageBox.Show(ex.Message, "エラー") Finally Application.Exit() End Try End Sub
private void Form1_Load(object sender, EventArgs e) { System.AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException); } private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) { try { Exception ex = (Exception)e.ExceptionObject; MessageBox.Show(ex.Message, "エラー"); } finally { Application.Exit(); } }
UnhandledExceptionイベントを使う場合は、次のような点に注意してください。
- ThreadExceptionイベントとは違い、Windows Forms アプリケーションだけでなく、コンソールアプリケーションでも使えます。
- ThreadExceptionイベントとは違い、メインスレッド以外のスレッドで例外がスローされたときも発生します。ただし、メインスレッドでスローされる例外について調べる場合は、ThreadExceptionイベントを使ったほうが良いでしょう。理由は、後述します。
- .NET Framework 1.1以前では、メインスレッド以外のスレッドでスローされた例外によりThreadExceptionイベントが発生した場合は、アプリケーションが終了しません(UnhandledExceptionEventArgs.IsTerminatingプロパティがFalseになります)。
- .NET Framework 1.1以前では、メインのアプリケーションドメイン(アプリケーションの起動時にシステムによって作成されたアプリケーションドメイン)のみで有効です。
- メインスレッドで例外がスローされたときは、「アプリケーションのコンポーネントで、ハンドルされていない例外が発生しました。...」というダイアログが表示され、UnhandledExceptionイベントは発生しません。MSDN「AppDomain.UnhandledException イベント」には、「.NET Framework Version 1.0 および 1.1 では、このイベントが発生する前に、アプリケーションの終了とデバッグ オプションがユーザーに報告されます。」とありますが、その後にUnhandledExceptionイベントが発生しませんし、.NET Framework 2.0以降でも同じ症状が出ます。この問題について詳しくは、「Console apps and AppDomain.CurrentDomain.UnhandledException」をご覧ください。
Visual Studio 2005以降のVB.NETで、My.Application.UnhandledExceptionイベントを使用する方法
Visual Studio 2005以降のVB.NETでは、My.Application.UnhandledExceptionイベントを使用することができます。
My.Application.UnhandledExceptionイベントハンドラは、ApplicationEvents.vbに記述すると便利です。ApplicationEvents.vbは、プロジェクトのプロパティの「アプリケーション」タブにある「アプリケーションイベントの表示」ボタンをクリックすることにより表示できます。(プロジェクトのプロパティは、メニューの「プロジェクト」-「プロパティ」で表示できます。)
以下にApplicationEvents.vbにUnhandledExceptionイベントハンドラを記述した例を示します。
Namespace My Partial Friend Class MyApplication Private Sub MyApplication_UnhandledException( _ ByVal sender As Object, _ ByVal e As Microsoft.VisualBasic.ApplicationServices. _ UnhandledExceptionEventArgs) _ Handles Me.UnhandledException Try e.ExitApplication = True MsgBox(e.Exception.Message, MsgBoxStyle.Critical, "エラー") Finally Application.Exit() End Try End Sub End Class End Namespace
UnhandledExceptionイベントを使用する際の注意点を以下にあげます。
- アプリケーションフレームワークが有効になっている必要があります。デフォルトで有効になっていますが、変更するには、プロジェクトのプロパティの「アプリケーション」タブの「アプリケーションフレームワークを有効にする」を変更します。
- 私の試した限りでは、Application.ThreadExceptionイベントとほぼ同じようです。注意点もThreadExceptionイベントで指摘した点がそのまま当てはまります。
- 履歴:
- 2008/11/23 「Visual Studio 2005以降のVB.NETで、My.Application.UnhandledExceptionイベントを使用する方法」でアプリケーションを終了するコードが抜けているのを修正。
- 2010/7/22 リンク切れを修正。
注意:この記事では、基本的な事柄の説明が省略されているかもしれません。初心者の方は、特に以下の点にご注意ください。
0 comments:
Post a Comment