如何使用EurekaLog获取已处理异常的调用堆栈

时间:2017-10-23 03:20:16

标签: delphi eurekalog

我使用Delphi 7和EurekaLog 7(在兼容模式下)并且只想获得一个处理异常的调用堆栈,比如

procedure CrossThreadFunc;
begin
  try
    SomeCode;
  except
    on E: Exception do
      Log(CallStackOf(E));
  end;
end;

它是一个多线程应用程序,所以我希望尽可能看到调用线程的调用堆栈。此外,由于这是一个处理过的例外,我还需要使用EurekaLog的OnExceptionRaise事件吗? (我不想这样做。)

编辑:使用一些参数多次调用CrossThreadFunc(),我需要知道的就是我调用它的地方,最终导致SomeCode()引发异常。

1 个答案:

答案 0 :(得分:0)

EurekaLog's help中描述了几种方法:

选项1

(仅适用于Delphi 2009 +)

假设您只需要文字表示形式:

except
  on E: Exception do
    Memo1.Lines.Text := E.StackTrace;
end;

选项2

假设您有权访问RTL的异常对象:

uses
  EExceptionManager, // for ExceptionManager
  EException,        // for TEurekaExceptionInfo 
  ECallStack;        // for TEurekaBaseStackList 

var
  EI: TEurekaExceptionInfo;
  CallStack: TEurekaBaseStackList;
// ...
  except
    on E: Exception do
    begin
      EI := ExceptionManager.Info(E);
      // EI would be nil, if EurekaLog is disabled
      // or event handlers instruct EurekaLog to skip this exception
      if Assigned(EI) then 
        CallStack := EI.CallStack;
    end;
  end;

注意:由于某些旧版IDE中的错误,您可能需要这样写:

EI := ExceptionManager.Info(Pointer(E));

选项3

假设您有权访问EurekaLog的异常信息对象(例如事件处理程序中的参数):

uses
  EException, // for TEurekaExceptionInfo 
  ECallStack; // for TEurekaBaseStackList

{ ... } AExceptionInfo: TEurekaExceptionInfo; { ... }
var
  CallStack: TEurekaBaseStackList;
begin
  CallStack := AExceptionInfo.CallStack;
end;

选项4

假设您要为当前线程中的最后一个(例如最近)异常调用堆栈:

uses
  EExceptionManager, // for ExceptionManager
  EException,        // for TEurekaExceptionInfo 
  ECallStack;        // for TEurekaBaseStackList 

var
  EI: TEurekaExceptionInfo;
  CallStack: TEurekaBaseStackList;
begin
  EI := ExceptionManager.LastThreadException;
  // EI would be nil, if EurekaLog is disabled
  // or event handlers instruct EurekaLog to skip this exception
  if Assigned(EI) then 
    CallStack := EI.CallStack;
end;

注释:

  • 如果您需要当前的调用堆栈-使用GetCurrentCallStack单位中的ECallStack函数:

    用途   ECallStack; //用于TEurekaBaseStackList和GetCurrentCallStack

    过程TForm1.Button1Click(Sender:TObject); 变种   调用堆栈:TEurekaBaseStackList; 开始   CallStack:= GetCurrentCallStack;   //您也可以使用ECallStack单元中的其他功能   尝试     Memo1.Lines.Text:= CallStack.ToString;     //您还可以使用CallStackToString(s)例程来自定义文本格式   最后     FreeAndNil(CallStack);   结束; 结束;

  • 如果需要其他线程的调用堆栈-只需在选项中进行设置,所有启用的线程的调用堆栈都将包含在同一调用堆栈对象中。您可以通过调用堆栈条目的ThreadID属性来区分线程。

  • 如果出于记录目的需要将检索到的调用堆栈转换为文本/字符串表示形式,请参见this

选项1

使用异常对象的StackTrace属性(Delphi 2009 +):

except
  on E: Exception do
    Memo1.Lines.Text := E.StackTrace;
end;

选项2

使用ToString方法以默认格式将调用堆栈转换为单个字符串:

var
  CallStack: TEurekaBaseStackList;
begin
  CallStack := { ... somehow retrieve call stack ... };
  Memo1.Lines.Text := CallStack.ToString;
end;

选项3

使用Assign方法以默认格式将调用堆栈转换为TStrings对象:

var
  CallStack: TEurekaBaseStackList;
begin
  CallStack := { ... somehow retrieve call stack ... };
  Memo1.Lines.Assign(CallStack);
end;

选项4

使用CallStackToString单位中的ECallStack功能:

// (CallStackToString function allows you to override header and formatting)

var
  CallStack: TEurekaBaseStackList;
  Formatter: TCompactStackFormatter;
begin
  CallStack := { ... somehow retrieve call stack ... };

  // A): Default formatting and header:
  Memo1.Lines.Text := CallStackToString(CallStack);

  // B): With custom header:
  Memo1.Lines.Text := CallStackToString(CallStack, 'Error Details:');

  // C): Custom formatting:
  Formatter := TCompactStackFormatter.Create;
  try
    // <- here you can customize Formatter (for example: alter captions for columns, etc.)
    Memo1.Lines.Text := CallStackToString(CallStack, '', Formatter);
  finally
    FreeAndNil(Formatter);
  end;
end;

选项5

使用CallStackToStrings单位中的ECallStack功能:

// (CallStackToStrings function allows you to override header and formatting)

var
  CallStack: TEurekaBaseStackList;
  Formatter: TCompactStackFormatter;
begin
  CallStack := { ... somehow retrieve call stack ... };

  // A): Default formatting and header:
  CallStackToStrings(CallStack, Memo1.Lines);

  // B): With custom header:
  CallStackToStrings(CallStack, Memo1.Lines, 'Error Details:');

  // C): Custom formatting:
  Formatter := TCompactStackFormatter.Create;
  try
    // <- here you can customize Formatter (for example: alter captions for columns, etc.)
    CallStackToStrings(CallStack, Memo1.Lines, '', Formatter);
  finally
    FreeAndNil(Formatter);
  end;
end;

可用的格式化程序有:

  • TEurekaStackFormatter-EurekaLog样式的调用堆栈的通用格式化程序(即带有列的固定宽度表)-最好在文本文件中使用
  • TEurekaStackFormatterV6-向后兼容的格式化程序,以EurekaLog V6格式(较少列)生成调用堆栈
  • TSimpleStackFormatter-生成适合可变宽度字体(最好在消息框中使用)的调用列表的列表视图(无列)
  • TCompactStackFormatter-与TSimpleStackFormatter相似,但产生的紧凑输出少了细节(便于快速预览)

P.S。您可能还需要考虑使用EurekaLog's logging procedures