在尝试除块之前,在Delphi Application.OnException中捕获异常

时间:2017-02-01 17:56:44

标签: delphi try-catch 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事件。

有没有办法先在Application.OnException事件而不是except块中捕获它?

2 个答案:

答案 0 :(得分:6)

仅为未处理的例外调用Application.OnException处理程序。

未处理的异常是指没有try..except块已捕获异常或已被捕获然后重新引发的异常。

使用一些简单的例子来演示,让我们假设这实际上是应用程序中唯一的代码,并且没有其他异常处理程序......

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

答案 1 :(得分: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中处理它。我避免使用一些第三方框架进行这种简单的日志记录。