2017-02-01 5 views
0

delphiアプリケーションで発生したすべての例外をログに記録します。 そのために、私はプロジェクトのソースコード内で自分自身のものでApplication.OnExceptionイベントをオーバーライドしました。例外をブロックする前にDelphi Application.OnExceptionで例外をキャプチャします。

program Project; 

uses 
    Vcl.Forms, 
    Unit1 in 'Unit1.pas' {Form1}, 
    Logger in 'Logger.pas', 
    JCLDebugHandler in 'JCLDebugHandler.pas'; 

{$R *.res} 

begin 
    Application.Initialize; 
    Application.OnException := TApplicationException.AppException; 
    Application.MainFormOnTaskbar := True; 
    Application.CreateForm(TForm1, Form1); 
    Application.Run; 
end. 

これは完全に機能しますが、このソリューションではtry-exceptブロックにキャッチされた例外をキャッチするのに失敗しています。

例外がexceptブロックでキャッチされると、Application.OnExceptionイベントがトリガーされません。

exceptブロックではなくApplication.OnExceptionイベントで最初にキャッチする方法はありますか?

+0

を参照してください。おそらく:http://stackoverflow.com/a/6415902/327083 –

+0

関連:http://stackoverflow.com/q/2628751/327083 –

+5

だけmadExceptを使用してジョブがJCLコンポーネント –

答えて

6

ハンドラは、未処理の例外に対してのみ呼び出されます。

未処理の例外は、ブロックが例外をキャッチしていない場合、またはキャッチされてから再発生した場合です。のは、これが事実上のアプリケーションでのコードのみであり、他の例外ハンドラが存在しないことと仮定しましょう、証明するためにいくつかの些細な例を使用して

...この場合

try 
    a := 42/0; 
except 
    on EDivisionByZero do 
    begin 
    Log.i('Silly division by zero error has been logged'); 
    raise; 
    end; 
end; 

は、例外がキャッチされているが、アプリケーションは例外を処理するための戦略を持たず、単にそれが発生したことを記録し、例外を再発生させます。実行は任意の外側のexceptブロックで継続されます。存在しない場合、または存在する可能性がある場合例外を再発行すると、例外はApplication.OnExceptionハンドラに到達します。

しかし、例外ハンドラが例外を再調達する必要はありません。この場合

try 
    a := 42/0; 
except 
    on EDivisionByZero do 
    a := 0; 
end; 

を、例外ハンドラがゼロ除算を処理し、コードがに満足しているので、それを再提起しません。その場合はゼロの結果を続行します(ありませんが、これは単なる例です)。

例外が最初の場所で起こったことがなかったかのように例外が(try..exceptブロックの後)の再引き上げ、実行が進むではありませんので。あなたのApplication.OnExceptionはそれについて決して知りません。要約すると

Application.OnException未処理例外に対処するためにあなたの最後のチャンスです。 最初に機会に対応する機会はありません。は、例外です。

アプリケーションコードが応答する前に例外を傍受するか、である可能性がありますが、かなり進歩したものであり、単純なメカニズムは「そのまま」提供されていません。

は幸いにも、あなたがあなたのアプリケーションに導入しようとしている機能を提供することができることを使用することができますサードパーティのライブラリがあります。

A popular one for Delphi which you might wish to check out is madExcept

0

私は最終的にすべての例外のキャプチャとロギングにJCLを使用しました。私は、次のコードで新しい.PASファイルを作成:このコードで

/// <summary> 
/// Inicializa JCL para capturar la informacion necesaria de la excepcion. 
/// </summary> 
initialization 
    JclAddExceptNotifier(SetExceptionError); 
    JclStackTrackingOptions := JclStackTrackingOptions + [stExceptFrame]; 
    JclStartExceptionTracking; 

/// <summary> 
/// Finaliza la notificacion de JCL luego de capturar la informacion necesaria de la excepcion. 
/// </summary> 
finalization 
    JclRemoveExceptNotifier(SetExceptionError); 
end. 

を、私は例外を捕捉し、私の関数SetExceptionErrorでそれを扱うことができます。私は、この単純なロギングのためにいくつかの第三者フレームワークの使用を避けていました。

関連する問題