Записать исключение в 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-exc.

Когда исключение перехватывается в блоке исключений, оно просто не вызывает событие Application.OnException.

Есть ли способ сначала перехватить его в событии Application.OnException, а не в блоке кроме?

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вашпоследний шанс разобраться с необработанным исключением. Это не первая возможность ответить на любое исключение.

Перехват исключений в момент их возникновения до того, как какой-либо код приложения будет иметь возможность реагировать или иметь дело с ними, возможен, но это довольно сложный процесс, и простой механизм не предоставляется "из коробки".

К счастью, вы можете использовать сторонние библиотеки, которые могут предоставить возможности, которые вы хотите внедрить в свое приложение.

Популярным для Delphi, который вы можетепопробовать, является madExcept.

Я наконец использовал 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. Я избегал использования каких-либо сторонних фреймворков для этой простой регистрации.

Другие вопросы по тегам