1. ホーム
  2. c#

64 ビット版 Windows の WinForms アプリケーションで VS2010 が未処理の例外メッセージを表示しない

2023-09-17 19:01:22

質問

新しいプロジェクトを作成すると、処理されない例外について奇妙な動作が発生します。これは、私がこの問題を再現する方法です。

1) 新しい Windows Forms アプリケーションを作成します (C#, .NET Framework 4, VS2010)

2) 次のコードを Form1_Load ハンドラーに追加します。

int vara = 5, varb = 0;
int varc = vara / varb;
int vard = 7;

私は、VSが2行目でブレークし、処理されない例外メッセージを表示することを期待します。しかし、何が起こるかというと、3 行目は何のメッセージもなくただスキップされ、アプリケーションは実行され続けます。

私の既存の C# プロジェクトでは、この問題は発生しません。したがって、私の新しいプロジェクトは、いくつかの奇妙なデフォルト設定で作成されているのだと思います。

誰か私のプロジェクトに何が間違っているのかわかりますか?

Debug->Exceptionsにチェックを入れてみました。しかし、その後、例外を try-catch ブロックの中で例外を処理しても、実行が中断されます。私の記憶が正しければ、このダイアログボックスに "unhandled exceptions" と呼ばれる列があり、私が望むことと全く同じことができるはずです。しかし、私のプロジェクトでは、1 つの列 ("Thrown") しかありません。

どのように解決するのですか?

これは、64 ビット版の Windows 7 上で 32 ビット コードの実行を可能にする wow64 エミュレーション レイヤーによって引き起こされる厄介な問題です。 これは、64 ビット ウィンドウ マネージャーによって生成された通知に応答して実行されるコード内の例外を飲み込みますが、例えば Load イベントのような 64 ビットのウィンドウ マネージャーによって生成された通知に応答して実行されるコードの例外を飲み込みます。 デバッガーがそれを見て踏み込むのを防ぐ。 この問題は解決が難しく、MicrosoftのWindowsグループとDevDivグループは指をくわえて見ている状態です。 DevDiv はそれについて何もできず、Windows はそれが正しく文書化された動作であると考えていますが、不思議なことにそう聞こえるのです。

それは確かに 文書化された が、その結果を理解したり、それが妥当な動作であると考える人はほとんどいません。 特に、ウィンドウ プロシージャが表示されない場合、ウィンドウ プロシージャを隠すためにラッパークラスを使用するプロジェクトと同じように、表示されません。 WinformsやWPF、MFCのアプリのように。 根本的な問題は、32 ビット コードから、通知をトリガーした 64 ビット コードに戻り、例外を処理またはデバッグしようとする 32 ビット コードに戻る例外をフローする方法を Microsoft が見いだせなかったことです。

これは、デバッガーが接続されている場合にのみ発生する問題で、デバッガーがなくてもコードは通常どおり動作します。

プロジェクト > プロパティ > ビルド タブ > プラットフォーム ターゲット = AnyCPU と Prefer 32-bit のチェックボックスをオフにします。 アプリは 64 ビット プロセスとして実行され、wow64 障害モードが解消されます。 いくつかの影響として、VS2013 より前のバージョンの VS では編集+続行が無効になり、32 ビット コードに依存している場合、常に可能とは限りません。

他の可能な回避策。

  • デバッグ > 例外 > CLR 例外に対して Thrown ボックスをチェックし、デバッガが例外をスローするコード行で強制的に停止するようにします。
  • で try/catch を記述します。 Load イベントハンドラで try/catch を記述し、catch ブロックで failfast を記述します。
  • 使用する Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException) の中に Main() メソッドに追加することで、メッセージループの例外トラップがデバッグモードで無効にならないようにします。 しかし、これではすべての未処理の例外をデバッグすることが難しくなってしまいます。 ThreadException イベントはかなり役に立ちません。
  • あなたのコードが本当に Load イベントハンドラに属するかどうか考えてみてください。 しかし、VB.NET では非常によく使われるイベントで、デフォルトのイベントであり、ダブルクリックでイベントハンドラを追加できるため、白鳥の歌のようなものです。 あなたはこれまで 本当に が必要なのは Load は、ユーザー設定とオートスケーリングが適用された後の実際のウィンドウサイズに興味がある場合に必要です。 他のすべてはコンストラクタに属します。
  • Windows 8 以降に更新すると、この wow64 問題が解決されます。