in Grijjy.ErrorReporting.pas we can not get the stacktrace report of a particular exception we catch in try... except end. I mean their is no way in a try .. except block to do something like MyReport := BuildExceptionReport(...), the only way is to catch the report in the event message. To handle this i updated the function below :
procedure TgoExceptionReporter.ReportException(const AExceptionObject: TObject;
const AExceptionAddress: Pointer);
var
E: Exception;
ExceptionMessage: String;
CallStack: TgoCallStack;
ExceptionLocation: TgoCallStackEntry;
Report: IgoExceptionReport;
I: Integer;
begin
{ Ignore exception that occur while we are already reporting another
exception. That can happen when the original exception left the application
in such a state that other exceptions would happen (cascading errors). }
if (FReportingException) then
Exit;
FReportingException := True;
try
CallStack := nil;
if (AExceptionObject = nil) then
ExceptionMessage := 'Unknown Error'
else if (AExceptionObject is Exception) then
begin
E := Exception(AExceptionObject);
ExceptionMessage := E.Message;
if (E.StackInfo <> nil) then
begin
CallStack := GetCallStack(E.StackInfo);
for I := 0 to Length(Callstack) - 1 do
begin
{ If entry in call stack is for this module, then try to translate
the routine name to Pascal. }
if (CallStack[I].ModuleAddress = FModuleAddress) then
CallStack[I].RoutineName := goCppSymbolToPascal(CallStack[I].RoutineName);
end;
end;
end
else
ExceptionMessage := 'Unknown Error (' + AExceptionObject.ClassName + ')';
ExceptionLocation.Clear;
ExceptionLocation.CodeAddress := UIntPtr(AExceptionAddress);
GetCallStackEntry(ExceptionLocation);
if (ExceptionLocation.ModuleAddress = FModuleAddress) then
ExceptionLocation.RoutineName := goCppSymbolToPascal(ExceptionLocation.RoutineName);
Report := TgoExceptionReport.Create(ExceptionMessage, ExceptionLocation, CallStack);
try
TMessageManager.DefaultManager.SendMessage(Self,
TgoExceptionReportMessage.Create(Report));
except
{ Ignore any exceptions in the report message handler. }
end;
finally
FReportingException := False;
end;
end;
function TgoExceptionReporter.internalBuildExceptionReport(const AExceptionObject: TObject; const AExceptionAddress: Pointer): IgoExceptionReport;
var
E: Exception;
ExceptionMessage: String;
CallStack: TgoCallStack;
ExceptionLocation: TgoCallStackEntry;
I: Integer;
begin
CallStack := nil;
if (AExceptionObject = nil) then
ExceptionMessage := 'Unknown Error'
else if (AExceptionObject is Exception) then
begin
E := Exception(AExceptionObject);
ExceptionMessage := E.Message;
if (E.StackInfo <> nil) then
begin
CallStack := GetCallStack(E.StackInfo);
for I := 0 to Length(Callstack) - 1 do
begin
{ If entry in call stack is for this module, then try to translate
the routine name to Pascal. }
if (CallStack[I].ModuleAddress = FModuleAddress) then
CallStack[I].RoutineName := goCppSymbolToPascal(CallStack[I].RoutineName);
end;
end;
end
else
ExceptionMessage := 'Unknown Error (' + AExceptionObject.ClassName + ')';
ExceptionLocation.Clear;
ExceptionLocation.CodeAddress := UIntPtr(AExceptionAddress);
GetCallStackEntry(ExceptionLocation);
if (ExceptionLocation.ModuleAddress = FModuleAddress) then
ExceptionLocation.RoutineName := goCppSymbolToPascal(ExceptionLocation.RoutineName);
result := TgoExceptionReport.Create(ExceptionMessage, ExceptionLocation, CallStack);
end;
procedure TgoExceptionReporter.ReportException(const AExceptionObject: TObject;
const AExceptionAddress: Pointer);
var
Report: IgoExceptionReport;
begin
{ Ignore exception that occur while we are already reporting another
exception. That can happen when the original exception left the application
in such a state that other exceptions would happen (cascading errors). }
if (FReportingException) then
Exit;
FReportingException := True;
try
Report := internalBuildExceptionReport(AExceptionObject, AExceptionAddress);
try
TMessageManager.DefaultManager.SendMessage(Self,
TgoExceptionReportMessage.Create(Report));
except
{ Ignore any exceptions in the report message handler. }
end;
finally
FReportingException := False;
end;
end;
class function TgoExceptionReporter.BuildExceptionReport(const AExceptionObject: TObject; const AExceptionAddress: Pointer): IgoExceptionReport;
begin
if Assigned(FInstance) then
result := FInstance.internalBuildExceptionReport(AExceptionObject, AExceptionAddress)
else
result := nil;
end;