Windows Error Reporting Part.3

Part.1 と Part.2 で WER の仕組みと前提となる SEH の概要をお伝えしました。Part.3 では、いよいよ WER の
API を紹介したいと思います。

Windows Error Reporting Part.1 で WER は Microsoft WER サイトに採取したデータを送信し、
その動きをレジストリで制御することができると紹介しましたが、API を使うと、一時的に現在のプロセスの設定のみを
変更することができます。

一つだけ注意があります。WerGetFlags() は、WerSetFlags() の結果を取得するときに使う用途になっているので
WerSetFlags() を呼び出さずに、いきなり WerGetFlags() を呼びだすと、エラーになります。

次に、WER の問題レポートの作成ですが、MSDN にある

に従い、以下の流れで処理します。

  1. WER_REPORT_INFORMATION 構造体を準備する
  2. WerReportCreate() を呼び出し、WER 問題レポートを作成する
  3. WerReportSetParameter() を呼び出して、パラメーターを追加する
  4. WerReportAddFile() を呼び出して、レポートに独自のファイルを追加する
  5. WerReportAddDump() を呼び出して、ミニダンプをレポートに追加する
  6. WerReportSubmit() を呼び出して、レポートを送信するか、ローカルキューに保存する
  7. WerReportCloseHandle() でリソースを解放して終了する

イメージがわかるように、実際の画面との対応を行ってみます。
まず、WER 問題レポートの表示です。

この投稿の続きを読む

Windows Error Reporting Part.2

Part.1 では、WER の概要をお伝えしました。Part.2 では、実際に WER の API を紹介したいところですが
WER の前提として、知っておかなければならない知識があります。例外処理についてです。

C++ では、構造化例外処理(SEH: Structured Exception Handling)と C++ 例外処理の 2 種類を使うことが
できます。SEH は OS が提供しているもので、C++ 例外処理は名前の通り、C++ 言語が提供しています
WER を使いこなすためには、SEH を理解しておく必要があります。
C++ の例外処理は別の機会でネタにして、今回は SEH の最低限の知識を復習します。

SEH は、__try/__except や __try/__finally を使い実装しますが、代表的な使い方はこんな感じです。

void MyFunc (void)
{
    __try
    {
        __try
        {
            // 処理
        }
        __except (EXCEPTION_EXECUTE_HANDLER)
        {
            // 例外ハンドラ
            // __try ブロック内で何かしらの例外処理が発生したときに 実行される
        }
    }
    __finally
    {
        // 終了ハンドラ
        // 例外が有ろうと無かろうと常に実行される。後処理で使うことが多い
    }
}

__except では、例外フィルターを指定するのですが、使うことができるのは

  • EXCEPTION_EXECUTE_HANDLER
    対応する __try ブロック内で例外処理が発生すれば、必ず実行される
  • EXCEPTION_CONTINUE_SEARCH
    呼び出しチェイン内の上位にある次の __except ブロックを実行させる
  • EXCEPTION_CONTINUE_EXECUTION
    対応する __try ブロック内で発生した例外を無視する

の 3 つです。図に書くと、次のような動きになります。

この投稿の続きを読む

Windows Error Reporting Part.1

ちょっと深いデバッグネタを紹介していきたいと思います。
Vista 以降、OS がアプリケーションに対して提供するデバッグアーキテクチャは大きく変更されました。

XP/2003 までは、ワトソン博士というのがあったのですが、Vista 以降は、大体、こんな仕組みで動いています。
カーネルが介入することによって、エラーロジック(ワトソン博士)そのもののエラーがなくなったので、
ほぼ間違いなく、エラー処理が実行されるというわけです。

デバッグアーキテクチャ

  1. WER サービス(WerSvc)は、OS ブート時にカーネルに対して、ポートを登録する。
  2. アプリケーションエラーは、一番最初に、カーネルが検知する。そして、カーネルがアプリケーションに
    対して、エラーが発生したことを通知するわけです。(これが、First Chance)
  3. アプリケーションの例外ハンドラーや、未処理の例外はカーネルに対して EXCEPTION_CONTINUE_SEARCH を
    返す。
  4. カーネルは、ポートを通して、WerSvc を呼び出す。
  5. WerSvc は、Windows Problem Reporting(Windows 問題レポート: werfault.exe)を呼び出し、画面表示する。
  6. もし、JIT デバッガが有効になっていたら、エラーを起こしたアプリケーションにデバッガをアタッチさせる。
  7. Windows Problem Reporting は、JIT デバッガを起動したことをカーネルに返し、カーネルはデバッガに例外を
    ディスパッチする。

WER_サービス

アプリケーションがエラーになった際に表示される以下の画面ですが、これが werfault.exe です。

この投稿の続きを読む