How to maintain the source line that throws an exception and add user information?

Our application registers the source string, throwing an exception with the JCL, and works just fine. I am using D2007. I have a TApplicationEvents.OnException event that does the actual logging. Consider this:

function MyFunc: String; begin // Codelines that may raise exception. // Call functions that also may raise exception end; procedure ComplexFunc(aVariable: String); begin // also here can it be exceptions.... // Code here that is the cause of exception end; procedure foo; var myVar: String; begin myvar := MyFunc; ComplexFunc(myvar); end; procedure TMainForm.ApplicationEvents1Exception(Sender: TObject; E: Exception); begin LogLastException(E, 'Unhandled Exception (%s)', [E.Message], 20); end; 

I have 3 methods and my onException event. LogLastException logs the column when an exception occurs. The problem is that I cannot add information to E.Message without losing the source that throws the exception. Pretend this is the second line in ComplexFunc that throws an exception. I also want to write the value of the myvar variable. Therefore, I change the code to:

 function MyFunc: String; begin // Codelines that may raise exception. // Call functions that also may raise exception end; procedure ComplexFunc(aVariable: String); begin // also here can it be exceptions.... // Code here that is the cause of exception end; procedure foo; var myVar: String; begin try myvar := MyFunc; ComplexFunc(myvar); except on E: Exception do raise TException.CreateFmt('myvar = %s', [myvar]); end; end; procedure TMainForm.ApplicationEvents1Exception(Sender: TObject; E: Exception); begin LogLastException(E, 'Unhandled Exception (%s)', [E.Message], 20); end; 

Now the myvar value is registered, BUT for the price I lose the original exception surrolin. Instead, a line with a raise of TException.CreateFmt is written. Any suggestion on how to do both?

Hello

+4
source share
5 answers

In addition to Marjan Vennema's answer (which I will follow), you can raise your new exception and make it look like it came from the address of the old exception.

 except on E: Exception do raise Exception.CreateFmt('myvar = %s', [myvar]) at ExceptAddr; end; 
+5
source

You lose the original source exception line because

  except on E: Exception do raise TException.CreateFmt('myvar = %s', [myvar]); end; 

effectively handles the original exception (makes it go away) and raises a new one. Which, of course, will have its own "source exception string".

The @balazs solution saves the source line of the original exception in the message of the new exception. @Stephane's solution comes close to the one I would use. Unfortunately, it replaces the original message only with myvar. What I would do is add a line on top of the original message, and then simply re-create the exception:

 except on E: Exception do begin E.Message := Format('%s'#13#10'%s', [Format('MyVar: %s', [MyVar]), E.Message]); raise; end; end; 
+3
source

Have I tried something like this?

  try myvar := MyFunc; ComplexFunc(myvar); except on E: Exception do begin e.message := format('myvar = %s', [myvar]); raise ; end; end; 
+2
source

I do not know what LogLastException does, but if you can redirect its result to a string and not to your log, you can do a reposition as follows:

  except on E: Exception do begin str := LogLastExceptionToString(E, 'Unhandled Exception (%s)', [E.Message], 20); raise TException.CreateFmt( str + 'myvar = %s message so far:' , [myvar]); end; end; 
+1
source

A simple approach would be to define a global variable, assign it additional information, and then add its contents to your log when registering exception information.

0
source