Delphi 如何记录导致异常的源行并添加自定义信息?

Delphi 如何记录导致异常的源行并添加自定义信息?,delphi,exception-handling,delphi-2007,Delphi,Exception Handling,Delphi 2007,我们的应用程序使用JCL记录导致异常的源代码行,它工作得很好。 我用D2007。我有一个TApplicationEvents.OnException事件,它执行实际的日志记录。 考虑这一点: function MyFunc: String; begin // Codelines that may raise exception. // Call functions that also may raise exception end; procedure ComplexFunc(aV

我们的应用程序使用JCL记录导致异常的源代码行,它工作得很好。 我用D2007。我有一个TApplicationEvents.OnException事件,它执行实际的日志记录。 考虑这一点:

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;
我有3个方法和我的OneException事件。 LogLastException在发生异常时记录调用堆栈。问题是,我无法在不丢失导致异常的源代码行的情况下向E.Message添加信息。假设它是ComplexFunc中引发异常的第二行。我还想记录myvar变量的值。因此,我将代码更改为:

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;
现在,myvar的值被记录下来,但以我丢失异常的原始源代码行为代价。而是记录带有raise TException.CreateFmt的行。有没有关于如何做到这两个方面的建议


关于

我不知道LogLastException是做什么的,但是如果您可以将它的结果重定向到字符串而不是日志中,您可以像这样重新释放异常:

  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;

我试过类似的东西吗

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

您正在丢失异常的原始源行,因为

  except
    on E: Exception do
      raise TException.CreateFmt('myvar = %s', [myvar]);
  end; 
有效地处理原始异常(使其消失)并引发新异常。当然,这将有自己的“例外源行”

@balazs的解决方案在新异常的消息中保留原始异常的源行@Stephane的解决方案与我使用的方案非常接近。不幸的是,他正在用myvar的值替换原始消息。我要做的是在原始消息的顶部添加一行,然后重新引发异常:

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

除了Marjan Vennema的答案(我将遵循),您还可以提出新的异常,并使其看起来像来自旧异常的地址

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

一种简单的方法是定义一个全局变量,为其分配额外的信息,然后在记录异常信息时将其内容添加到日志中。

+1从未想过这样使用它。每天学习新的东西…:-)