- PR -

Windowsアプリケーションのデバッガ起動時の挙動の違い

投稿者投稿内容
未記入
会議室デビュー日: 2007/01/04
投稿数: 5
投稿日時: 2007-04-10 19:31
お世話になっております。
Visual Studio 2005 Team EditionでWindowsアプリケーションを作成していますが、
「デバッグ開始」と「デバッグなしで開始」で挙動が異なり困っています。

やりたいこと:
・Windowsアプリケーションを作成中
・UnhandledExceptionEventHandlerの実装により、try〜catchブロックをすり抜けた例外を
WindowsFormの呼び出し元で全てまとめてキャッチしたい

実装:
※確認用のため、意図的にエラーを発生させています

Program.cs-----------------------------------------

Thread.GetDomain().UnhandledException
  += new UnhandledExceptionEventHandler(Program_UnhandledException);

static void Main()
{
  try
  {
    Application.Run(new TestForm());
  }
  catch
  {
    // エラー処理
  }
}

private static void Program_UnhandledException
  (object sender, UnhandledExceptionEventArgs e)
{
  // エラー処理
}

---------------------------------------------------
TestForm.cs----------------------------------------

// 中略
throw new Exception();
// 後略

---------------------------------------------------


現象:
【『デバッグ開始』で起動した場合】
・Program.csのMainメソッドを囲むtry〜catchブロックにExceptionがキャッチされる
・上記のtry〜catchブロックをコメントアウトした場合、
Program_UnhandledExceptionメソッドにExceptionがキャッチされる

【『デバッグなしで開始』で起動した場合】
・try〜catchブロックにもProgram_UnhandledExceptionメソッドにもキャッチされない

Mainメソッドのtry〜catchブロックすら抜けてしまうのですが、
Mainメソッドは『呼び出し元』であると判定されていないということでしょうか?
MSDNでApplication.Runメソッドやデバッグについて調べてみましたが、
関連しそうな情報を見つけられませんでした。

原因を思いつく方がいらっしゃいましたら、アドバイスをお願いいたします。
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2007-04-10 19:50
デバッグ無し なんだから、デバッガが止まるはずないやん


そういうことではなく?
_________________
未記入
会議室デビュー日: 2007/01/04
投稿数: 5
投稿日時: 2007-04-10 20:01
いえ、そういうことではありません(言葉が足りず申し訳ありません)。

デバッガが止まるかどうかではなく、
デバッグの有無によって
catchブロックもしくはProgram_UnhandledExceptionメソッドに
コードが到達する場合としない場合がある、ということを言いたかったんです。

# コードが到達する場合としない場合の見分け方については、
catchブロックもしくはProgram_UnhandledExceptionメソッドでは
独自に定義したMessageBoxを表示させているため、
それが表示されるかどうかで判断しています。
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2007-04-10 20:08
MessageBox ではなく、ファイルへの書き出しにしてみてください。
Application.Run の外ではメッセージポンプが止まってるから、メッセージボックスは出ないかも知れない。
_________________
未記入
会議室デビュー日: 2007/01/04
投稿数: 5
投稿日時: 2007-04-10 20:33
> MessageBox ではなく、ファイルへの書き出しにしてみてください。
>Application.Run の外ではメッセージポンプが止まってるから、メッセージボックスは出ないかも知れない。

テキストファイルへ書き出すように変更して試してみましたが、やはりできませんでした。
「デバッグ開始」で実行すると、ちゃんとファイルが出力されるのですが。。。
こうなると、デバッグそれ自体に原因があるように思えてなりません。
囚人
ぬし
会議室デビュー日: 2005/08/13
投稿数: 1019
投稿日時: 2007-04-10 22:35
試してみましたが、両者に違いは生じませんでした。

何か他に出ていない情報はありませんか?
単純な例で済むなら、端折らないで、そのままコピー&ペーストして再現できるようなコードを書いてください。
_________________
囚人のジレンマな日々
未記入
会議室デビュー日: 2007/01/04
投稿数: 5
投稿日時: 2007-04-11 09:52
> 単純な例で済むなら、端折らないで、そのままコピー&ペーストして再現できるようなコードを書いてください。
単純化したコードを書いてみました。
なお、私の環境では、このコードで実行してみた結果は以下の通り、最初の投稿と同じでした。
デバッグあり:Main関数のcatchに例外がキャッチされる
デバッグなし:例外はキャッチされない

----------------Program.cs
using System;
using System.Windows.Forms;
using System.Threading;

static class Program{
  [STAThread]

  private delegate void DoSomethingDelegate();

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

  // 例外処理のイベントハンドラを登録
  Thread.GetDomain().UnhandledException +=
    new UnhandledExceptionEventHandler(Program_UnhandledException);

    try
    {
      // 別スレッドで事前処理
      DoSomethingDelegate d = new DoSomethingDelegate(doSomething);
      IAsyncResult result = d.BeginInvoke(null, null);

      // 別スレッドの完了をポーリング
      while (result.IsCompleted == false)
      {
        Application.DoEvents();
        System.Threading.Thread.Sleep(10);
      }

      // メインフォームの実行
      Application.Run(new MainForm());

    }
    catch (Exception ex)
    {
      MessageBox.Show("Mainメソッドのcatchに例外がキャッチされました\\\\n"+ex.Message);
    }
  }

  private static void Program_UnhandledException(object sender, UnhandledExceptionEventArgs e)
  {
    Exception ex = e.ExceptionObject as Exception;

    if (ex != null)
    {
      MessageBox.Show("UnhandledExceptionEventが発生しました\\\\n"+ex.Message);
    }
  }

  private static void doSomething()
  {
    // 事前処理
  }
}

----------------MainForm.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

public partial class MainForm : Form
{
  public MainForm()
  {
    InitializeComponent();
  }

  private void MainForm_Load(object sender, EventArgs e)
  {
    // わざと例外をスローする
    throw new Exception();
  }

}
未記入
会議室デビュー日: 2007/01/04
投稿数: 5
投稿日時: 2007-04-11 16:41
過去ログを見つけることが出来ました。
検索が足りずにスレッドを立ててしまい、申し訳ありませんでした。
http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=24387&forum=7

スキルアップ/キャリアアップ(JOB@IT)