I want use JCLDebug to log all exceptions raised, including the ones that are handled.
Is it possible to do that?
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.
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.
So, try... catch can only handle errors that occur in valid code. Such errors are called “runtime errors” or, sometimes, “exceptions”.
You can either use the try-catch-finally approach to handle all kinds of exceptions.
Take a look at JclAddExceptNotifier
in the JclHookExcept
unit.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With