有几种方法可以做到这一点,在EurekaLog 的帮助中有描述:
选项1
(仅限德尔福 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); var CallStack: TEurekaBaseStackList; 开始 CallStack := GetCurrentCallStack; // 你也可以使用 ECallStack 单元中的其他函数 try Memo1.Lines.Text := CallStack.ToString; // 您也可以使用 CallStackToString(s) 例程来自定义文本格式 finally FreeAndNil(CallStack); 结尾; 结尾;
如果您需要来自其他线程的调用堆栈 - 只需在选项中设置它,所有启用的线程的调用堆栈将包含在同一个调用堆栈对象中。ThreadID
您可以通过调用堆栈条目的属性来区分线程。
如果您需要将检索到的调用堆栈转换为文本/字符串表示以进行日志记录,请参见:
选项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,但产生更紧凑的输出和更少的细节(适合快速预览)
PS 你可能还想考虑EurekaLog 的日志记录程序。