4

現在、未処理の例外が発生した場合に別のプログラムにメッセージを送信する、Windows サービスに組み込まれた例外ハンドラーを作成しようとしています。メソッドを作成し、通信が機能するようになりましたが、プログラムがエラーをスローするたびに (強制するコードにレイズ呼び出しがあります)、ウィンドウが代わりにそれをキャッチし、ハンドラーが呼び出されないようです。誰かが私が間違っていることを説明できますか?.

説明する簡略化されたコード:

procedure unhandled();
  begin
    raise Exception.Create('Unhandled');
  end;

procedure ExceptionHandler(ExceptObject: TObject; ExceptAddr: Pointer);
  begin
    WriteLn('Display: ' + Exception(ExceptObject).Message);
    //send Message Here
  end;

このコードを呼び出して実行します。

WriteLn('Starting');    

ExceptProc := @ExceptionHandler;    

unhandled();

出力は次のようになると思います。

開始
表示: 未処理

しかし、それが行うのは表示だけです:

起動

その後、Windows は約 5 秒後にコマンド プロンプトを返します。

ハンドラーが正しく呼び出されないのはなぜですか?

PS テスト用のコンソール アプリでこれらのテストを実行しています。

編集:

さらに詳しい情報は次のとおりです。

明らかに、ExceptProc が割り当てられている場合、プログラムは通常の実行時エラー 217 をスローすべきではありません。これはウィンドウがキャッチしているものだと思いますが、私が見ることができることから、私のプログラムはそのランタイムエラーをスローしており、それをキャッチするための ErrorProc も取得できません。

4

2 に答える 2

8

SetErrorMode()への呼び出しがありません:

SetErrorMode(SEM_NOGPFAULTERRORBOX);

これは、OS未処理の例外フィルターがダイアログ ボックスを表示したり、デバッガー アタッチ ダイアログ ボックスを表示したりしないようにするために必要です。私のマシンで期待どおりに動作する完全なサンプルを次に示します。

{$apptype console}

uses Windows, SysUtils;

procedure unhandled();
begin
  raise Exception.Create('Unhandled');
end;

procedure ExceptionHandler(ExceptObject: TObject; ExceptAddr: Pointer);
begin
  Writeln('here');
  WriteLn('Display: ' + Exception(ExceptObject).Message);
  Flush(Output);
  Halt(1);
end;

procedure Go;
begin
  unhandled;
end;

begin
  ExceptProc := @ExceptionHandler;
  SetErrorMode(SEM_NOGPFAULTERRORBOX);
  Go;
end.

SetErrorMode() の効果は、実行中のプロセスのすべてのスレッドにわたってグローバルであることに注意してください。

于 2008-10-22T19:50:36.780 に答える
0

面白い。

カスタム例外ハンドラは、Delphi IDE (2007 で試行) でアプリを実行すると呼び出されますが、コマンド プロンプトから実行すると呼び出されません。

もう1つの興味深いこと-​​メインプログラムコードを次のように変更しました

begin
  WriteLn('Starting');
  try
    ExceptProc := @ExceptionHandler;
    Unhandled;
  finally Readln; end;
end.

Enterキーを押した後にのみ例外メッセージが表示されることに気付きました(Readlnへの入力を取得するため)。したがって、ハンドラーは例外が発生したときに呼び出されるのではなく、処理されたときに呼び出されます (すべてのコードをラップする暗黙の try..except で)。わかる。

この暗黙の try を使用する必要があります..その場合を除きますが、このマシンには Delphi 以外のデバッガーがなく、これ以上掘り下げることはできません。答えは他の誰かが知っているかもしれません...

于 2008-10-22T18:45:55.537 に答える