ページの作成:「== 概要 == Windowsフォームアプリケーションやコンソールアプリケーションを実装する際、例外が発生する可能性がある個所では…」 |
編集の要約なし |
||
| 1行目: | 1行目: | ||
== 概要 == | == 概要 == | ||
Windowsフォームやコンソールを実装する際、例外が発生する可能性がある個所では、 | |||
Try-Catch構文によりその例外をキャッチして適切な処置を施す必要がある。 | |||
しかし、現実には例外が正しくキャッチ(トラップ)されていないというケースは多々あり、 | しかし、現実には例外が正しくキャッチ(トラップ)されていないというケースは多々あり、 | ||
その場合にはアプリケーションの実行中に次のような.NET Framework標準のエラーダイアログが表示されてしまうことになる。 | その場合にはアプリケーションの実行中に次のような.NET Framework標準のエラーダイアログが表示されてしまうことになる。 | ||
[[ファイル:Catch exception 01.gif|フレームなし|中央]] | |||
このエラーダイアログは、一般ユーザにとって理解しにくい。PCの操作に自信のない人であれば、これを見た途端に困惑してしまう。 | |||
この事態を避けるために、.NET Framework標準のエラーダイアログを、ユーザライクな自作のエラーダイアログに切り替えたいという要望も多い。 | |||
ここでは、Windowsフォームやコンソールで処理されていない例外を1カ所でまとめてハンドルする方法を記載する。 | |||
この方法により、ハンドルしたメソッド内で独自に作成したエラーダイアログを表示すれば、前述の要望も実現可能である。 | |||
== 処理されていない例外をハンドルするには == | |||
# '''Application.ThreadExceptionイベントの活用''' | |||
処理されなかった例外をハンドルするには、WindowsフォームならApplicationクラス(System.Windows.Forms名前空間)の | |||
ThreadExceptionイベントをハンドルして処理する。 | |||
このイベントは、Windowsフォームのメインスレッド(ApplicationクラスのRunメソッドにより実行されるアプリケーションのコンテキスト)内で | |||
発生した未処理の例外をハンドルするためのものである。 | |||
# '''Thread.GetDomain().UnhandledExceptionイベントの活用''' | |||
では、上記のメイン・スレッド以外のコンテキスト上で発生した例外は、 | |||
現在のアプリケーションドメイン(AppDomainクラス(System名前空間)のThread.GetDomainメソッドにより取得できる)の | |||
UnhandledExceptionイベントで出来る。 | |||
例えば、マルチスレッド処理において、メインスレッド以外のスレッドで発生した例外やコンソールで発生した例外等は、 | |||
全てこのUnhandledExceptionイベントをハンドルして処理すればよい。 | |||
上記2つのイベントを活用して未処理の例外を実際に処理しているのが、次のサンプルコードである。 | |||
== サンプルコード == | |||
<source lang="cpp"> | |||
using System; | |||
using System.Windows.Forms; | |||
using System.Threading; | |||
namespace WindowsApplication1 | |||
{ | |||
public class Program | |||
{ | |||
[STAThread] | |||
static void Main() | |||
{ | |||
// ThreadExceptionイベント・ハンドラを登録する | |||
Application.ThreadException += new ThreadExceptionEventHandler(Application_ThreadException); | |||
// UnhandledExceptionイベント・ハンドラを登録する | |||
Thread.GetDomain().UnhandledException += new UnhandledExceptionEventHandler(Application_UnhandledException); | |||
// メイン・スレッド以外の例外はUnhandledExceptionでハンドル | |||
//string buffer = "1"; char error = buffer[2]; | |||
// ここで実行されるメインスレッドの例外はApplication_ThreadExceptionでハンドルできる | |||
Application.Run(new Form1()); | |||
} | |||
// 未処理例外をキャッチするイベントハンドラ | |||
// (Windowsアプリケーション用) | |||
public static void Application_ThreadException(object sender, ThreadExceptionEventArgs e) | |||
{ | |||
ShowErrorMessage(e.Exception, "Application_ThreadExceptionによる例外通知です。"); | |||
} | |||
// 未処理例外をキャッチするイベントハンドラ | |||
// (主にコンソール用) | |||
public static void Application_UnhandledException(object sender, UnhandledExceptionEventArgs e) | |||
{ | |||
Exception ex = e.ExceptionObject as Exception; | |||
if (ex != null) | |||
{ | |||
ShowErrorMessage(ex, "Application_UnhandledExceptionによる例外通知です。"); | |||
} | |||
} | |||
// ユーザー・フレンドリなダイアログを表示するメソッド | |||
public static void ShowErrorMessage(Exception ex, string extraMessage) | |||
{ | |||
MessageBox.Show(extraMessage + @" \n――――――――\n\n" + @"エラーが発生しました。開発元にお知らせください\n\n" + | |||
@"【エラー内容】\n" + ex.Message + "\n\n" + @"【スタックトレース】\n" + ex.StackTrace); | |||
} | |||
} | |||
} | |||
</source> | |||
<br><br> | |||
__FORCETOC__ | |||
[[カテゴリ:C_Sharp]] | |||