1

[更新2:問題は解決しました。以下のコメントと他の投稿を参照してください。これが誰かに役立つことを願っています。]

[更新:この質問の基礎となった、ベータテスト中の例外の検出に関する他の質問への回答に欠陥があります。Visual Studioの内部では、2010年と現在の2012年の両方がうまく機能しています。VSが行で中断した後、例外ハンドラーが呼び出され、続行すると言います。私はVS2012IDEの外でテストすることにしました、それは良いことです。OSはバグをトラップし、標準の「未処理の例外が発生しました」ダイアログを表示して、続行ボタンと終了ボタンとともに詳細を表示します。[続行]を選択すると、uber例外ハンドラーにトラップされることなくアプリケーションを続行できます。完全に選択すると、アプリケーションが白くなり、標準のウィンドウを閉じるダイアログが表示されます。終了ボタンも私のuberハンドラーを呼び出しません。

目的は、例外ハンドラーが呼び出されるようにすることです。VS2012 IDE内で作業している場合は、uber例外ハンドラーは必要ありません。ハンドラーの目的は、エンドユーザーとベータテスター、つまり私以外の、私の開発ステーションを持たない人を対象としています。

以下のコードはIDEの外部では機能しません。そのため、例外ハンドラーが呼び出されることはないため、[アプリを閉じる]と[続行]の2つのボタンは無意味です。IDEで実行し、コードで遊んでいる間(なぜそれが私の時間の無駄ではないのですか?)、続行は続行されず、終了は終了しません。同じ例外が何度も表示されます。はい、投稿された可能な回答を調べています。

このトピックは、.Net 4.5でよく使用され、解決されると思います。]

Application.Run(new frmMain())呼び出しの直前に追加した、メインフォームに依存しない未処理の例外ハンドラーを追加しました。ハンドラーは期待どおりに機能し、問題はありません。

質問:1。問題のあるフォームを強制的に閉じる/終了することは可能ですか?その場合はどうすればよいですか(基本的にアプリを閉じる)?

メインフォームにボタンを追加し、OnClickイベントで、単純にゼロで除算して、何か悪いことをうまくシミュレートしました。VS2012デバッグ環境で実行しています。当然、私は最初に問題のある行にヒットしました。これはVSが私を悩ませましたが、実行を続行すると、未処理の例外ハンドラーにヒットしました。そのハンドラー内の1つのオプションは、実行を終了することです。「Application.Exit()」を実行しましたが、効果がありませんでした。私はその問題のある行に戻り続けました。

  1. 例外ハンドラーからプログラムで次の行から実行を続行することは可能ですか?

単に戻るだけで、その時点に戻ることができます。

try / catchブロックについてはすでに知っていますが、ここでの目的は、予期しない未処理の例外をキャッチすることであり、最悪の場合、そのハンドラーから生成した意味のあるクラッシュレポートを送信できます。

JMKはいくつかのサンプルコードを要求しましたが、それが何を伴うのかはよくわかりません。

未処理の例外に応答してダイアログを表示します。この投稿の目的のために2つ、4つのボタンがあります。最初のボタンでユーザーは続行でき、2番目のボタンでアプリケーションを終了します。少なくとも、それは考えです。

        private void cmdContinue_Click(object sender, EventArgs e)
    {
        // Close this dialog and attempt to resume.
        this.DialogResult = DialogResult.OK;
        this.Close();
    }

    private void cmdExitApp_Click(object sender, EventArgs e)
    {
        // Close this dialog and attempt to resume.
        this.DialogResult = DialogResult.OK;
        this.Close();

        // Exit the application.
        Application.Exit();
    }

少なくともVS2012IDE内からの継続ブロックは、単に問題のある行に留まります。出口ブロックについても同様です。

私の例外に関する限り、例外は何でもかまいません。だから私はそれを書きました。私の専用の例外は、コードをテストすることだけで、ボタンはさようならです。私は勤勉になり、完璧な非破壊アプリケーションを作成しようとしていますが、その目標は幻想的であり、それまではこのブロックです。このメカニズムの他の目的は、ベータテスターがバグを私に報告することです。

これが私の超高速でダーティな未処理の例外のコードです。単純にゼロで除算するとコンパイラーに捕らえられるので、注意が必要でした。ちなみに、未処理の例外は通常、私が書いた特定の行ではなく、メソッド内の誰かのコードの呼び出しで発生します。

        private void button1_Click(object sender, EventArgs e)
    {
        // Attempt to throw and unhandled exception to test out the unhandled exception handler.
        int iDivider = 0;
        int iResult = 5 / iDivider;
    }

これが別のコードブロック、つまりテストアプリケーションの開始です。

        public static frmMain FormMain = null;

    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main()
    {
        // 
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);

        // Turn on global unhandled exception handling.
        cExceptions.Initialize();

        // Run the application load tasks manually, as Windows will not call this event until the show.
        Program.FormMain = new frmMain();

        Application.Run(Program.FormMain);
    }

誰かが私の例外ハンドラーを要求したので、ここにあります。基本的に、Microsoftがサンプルを提供しました。

    /// <summary>
/// Based on example at http://msdn.microsoft.com/en-us/library/system.appdomain.unhandledexception.aspx
/// </summary>
internal static class cExceptions
{
    [SecurityPermission(SecurityAction.Demand, Flags = SecurityPermissionFlag.ControlAppDomain)]
    public static void Initialize()
    {
        AppDomain currentDomain = AppDomain.CurrentDomain;
        currentDomain.UnhandledException += new UnhandledExceptionEventHandler(MyHandler);
    }

    static void MyHandler(object sender, UnhandledExceptionEventArgs args)
    {
        Exception ex = (Exception)args.ExceptionObject;


        // Log the exception to disk.

        // Show the exception information to the user.
        using (frmExceptions oException = new frmExceptions())
        {
            // Set the exeption information.
            oException.oEx = ex;

            // Show the dialog.
            oException.ShowDialog();
        }

        Console.WriteLine("MyHandler caught : " + ex.Message);
    }
}

前もって感謝します。

4

2 に答える 2

2

new frmMain())Application.Run の前に、クラス スコープ (つまり、フィールド) 内の参照を保持します。例外ハンドラーでそれを使用して frm.Close(); を呼び出します。

編集:2回目の読み取りでは、アプリを閉じたくないようです。むしろ、例外をスローしたフォームです。

ハンドラーで " " をフォームにキャストするobject senderと、それを閉じることができるはずです。以下のようなもの:

private void Exception_hander(object sender, EventArgs e) 
{ 
    if (sender is Form) 
    {
      ((Form)sender).Close();
    }
    else 
     { 
       ((Control)sender).Parent.Close();
     }
 } 
于 2012-10-04T16:06:37.720 に答える
0

さて、Google Uberlord は私に同情し、この素晴らしい記事が問題を解決しているのを見つけました。全能の Google に敬意を表します。

リンクは次のとおりです 。 http://www.switchonthecode.com/tutorials/csharp-tutorial-dealing-with-unhandled-exceptions

基本的に、JRadness のアイデアは正しかったのですが、わずかに誤りがありました。彼は使うべきだった

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

それよりも

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

Switch on the Code の著者は 3 つの方法について話しました。最初の方法は JRadness が提案したものであり、Windows フォームでは機能しません。

作成者は、Continue と Abort に関する私のもう 1 つの質問も解決しました。OS がバイパスされました。これが彼のイベント ハンドラーです。

public static void Application_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e)
{
    DialogResult result = DialogResult.Abort;
    try
    {
        Exception ex = (Exception)e.Exception;
        MessageBox.Show("Whoops! Please contact the developers with the"
             + " following information:\n\n" + e.Exception.Message + e.Exception.StackTrace,
             "Application Error", MessageBoxButtons.AbortRetryIgnore, MessageBoxIcon.Stop);
    }
    finally
    {
        if (result == DialogResult.Abort)
        {
            Application.Exit();
        }
    }
}

うん!!

于 2012-10-04T21:57:08.200 に答える