我使用Delphi 7和EurekaLog 7(在兼容模式下)并且只想获得一个处理异常的调用堆栈,比如
procedure CrossThreadFunc;
begin
try
SomeCode;
except
on E: Exception do
Log(CallStackOf(E));
end;
end;
它是一个多线程应用程序,所以我希望尽可能看到调用线程的调用堆栈。此外,由于这是一个处理过的例外,我还需要使用EurekaLog的OnExceptionRaise
事件吗? (我不想这样做。)
编辑:使用一些参数多次调用CrossThreadFunc(),我需要知道的就是我调用它的地方,最终导致SomeCode()引发异常。
答案 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;
可用的格式化程序有:
P.S。您可能还需要考虑使用EurekaLog's logging procedures。