【问题标题】:Capture exception in Delphi Application.OnException before try except block在尝试除块之前在 Delphi Application.OnException 中捕获异常
【发布时间】:2017-06-18 14:19:03
【问题描述】:

我想记录在 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 块中捕获它?

【问题讨论】:

标签: delphi try-catch onexception


【解决方案1】:

我终于使用 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 中处理它。我避免使用一些 3rd 方框架来进行这个简单的日志记录。

【讨论】:

    【解决方案2】:

    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 是您处理未处理异常的最后机会。这不是响应任何异常的第一次机会。

    在异常发生时拦截异常,在任何应用程序代码有机会做出反应或处理它们之前可能的,但这是非常先进的东西,并且没有提供简单的机制盒子”。

    幸运的是,您可以使用 3rd 方库,这些库可以提供您想要引入应用程序的功能。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-07-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-13
      • 2011-12-05
      相关资源
      最近更新 更多