Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to catch all exceptions (even those handled) with JCLDebug?

I want use JCLDebug to log all exceptions raised, including the ones that are handled.

Is it possible to do that?

like image 377
Rafael Cruz Avatar asked Jun 20 '11 17:06

Rafael Cruz


People also ask

How can I capture all exceptions?

Exception handling is used to handle the exceptions. We can use try catch block to protect the code. Catch block is used to catch all types of exception. The keyword “catch” is used to catch exceptions.

Does catch exception catch all exceptions?

The generic exception handler can handle all the exceptions but you should place is at the end, if you place it at the before all the catch blocks then it will display the generic message. You always want to give the user a meaningful message for each type of exception rather then a generic message.

Does try catch catch all errors?

So, try... catch can only handle errors that occur in valid code. Such errors are called “runtime errors” or, sometimes, “exceptions”.

Which of the following approaches is guaranteed to handle all kinds of exceptions?

You can either use the try-catch-finally approach to handle all kinds of exceptions.


2 Answers

Take a look at JclAddExceptNotifier in the JclHookExcept unit.

like image 197
Mason Wheeler Avatar answered Nov 15 '22 21:11

Mason Wheeler


It's not JCL based, but it's full Open Source and works from Delphi 5 up to XE.

This logging mechanism is able to intercept any exception.

In fact, since Delphi 6, you can define a global procedure in RtlUnwindProc to be lauched when any exception is raised:

{$ifdef DELPHI5OROLDER}
procedure RtlUnwind; external kernel32 name 'RtlUnwind';
{$else}
var
  oldUnWindProc: pointer;
{$endif}

procedure SynRtlUnwind(TargetFrame, TargetIp: pointer;
  ExceptionRecord: PExceptionRecord; ReturnValue: Pointer); stdcall;
asm
  pushad
  cmp  byte ptr SynLogExceptionEnabled,0
  jz   @oldproc
  mov  eax,TargetFrame
  mov  edx,ExceptionRecord
  call LogExcept
@oldproc:
  popad
  pop ebp // hidden push ebp at asm level
{$ifdef DELPHI5OROLDER}
  jmp RtlUnwind
{$else}
  jmp oldUnWindProc
{$endif}
end;


oldUnWindProc := RTLUnwindProc;
RTLUnwindProc := @SynRtlUnwind;

This code will launch the following function:

type
  PExceptionRecord = ^TExceptionRecord;
  TExceptionRecord = record
    ExceptionCode: DWord;
    ExceptionFlags: DWord;
    OuterException: PExceptionRecord;
    ExceptionAddress: PtrUInt;
    NumberParameters: Longint;
    case {IsOsException:} Boolean of
    True:  (ExceptionInformation : array [0..14] of PtrUInt);
    False: (ExceptAddr: PtrUInt; ExceptObject: Exception);
  end;
  GetExceptionClass = function(const P: TExceptionRecord): ExceptClass;

const
  cDelphiExcept = $0EEDFAE0;
  cDelphiException = $0EEDFADE;

procedure LogExcept(stack: PPtrUInt; const Exc: TExceptionRecord);
begin
  LastError := GetLastError;
     (...) intercept the exception
  SetLastError(LastError); // code above could have changed this
end;

For Delphi 5, I had to patch the VCL in-process, because there is no global exception interceptor.

like image 25
Arnaud Bouchez Avatar answered Nov 15 '22 21:11

Arnaud Bouchez