从C#打印堆栈跟踪信息

时间:2020-03-05 18:50:01  来源:igfitidea点击:

作为我们产品中某些错误处理的一部分,我们希望转储一些堆栈跟踪信息。但是,我们发现许多用户只会为错误消息对话框截图,而不是向我们发送该程序提供的完整报告的副本,因此我想在此对话框中提供一些最少的堆栈跟踪信息。

我的计算机上的.NET堆栈跟踪如下所示:

at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy)
at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, FileOptions options)
at System.IO.StreamReader..ctor(String path, Encoding encoding, Boolean detectEncodingFromByteOrderMarks, Int32 bufferSize)
at System.IO.StreamReader..ctor(String path)
at LVKWinFormsSandbox.MainForm.button1_Click(Object sender, EventArgs e) in C:\Dev\VS.NET\Gatsoft\LVKWinFormsSandbox\MainForm.cs:line 36

我有这个问题:

格式看起来是这样的:

at <class/method> [in file:line ##]

但是,在at和in关键字中,我假设这些关键字在运行时会本地化,例如运行挪威语.NET运行时而不是我安装的英语版本。

有什么办法让我以与语言无关的方式拆开堆栈跟踪,以便我只能显示具有此名称的那些条目的文件和行号?

换句话说,我想从上面的文本中获得以下信息:

C:\Dev\VS.NET\Gatsoft\LVKWinFormsSandbox\MainForm.cs:line 36

我们可以提供的任何建议都会有所帮助。

解决方案

回答

我们应该能够通过说出一个StackTrace对象而不是一个字符串

var trace = new System.Diagnostics.StackTrace(exception);

然后,我们可以自己查看框架,而无需依赖框架的格式。

另请参阅:StackTrace参考

回答

作为替代方案,log4net尽管有潜在危险,但比System.Diagnostics给我更好的结果。基本上在log4net中,我们有一个用于各种日志级别的方法,每个方法都有一个Exception参数。因此,当我们传递第二个异常时,它将把堆栈跟踪信息打印到我们配置的任何追加程序。

例如:Logger.Error(" Danger !!!",myException);

输出取决于配置,看起来像

System.ApplicationException: Something went wrong.
   at Adapter.WriteToFile(OleDbCommand cmd) in C:\Adapter.vb:line 35
   at Adapter.GetDistributionDocument(Int32 id) in C:\Adapter.vb:line 181
   ...

回答

这是我用来毫无例外地执行此操作的代码

public static void LogStack()
{
  var trace = new System.Diagnostics.StackTrace();
  foreach (var frame in trace.GetFrames())
  {
    var method = frame.GetMethod();
    if (method.Name.Equals("LogStack")) continue;
    Log.Debug(string.Format("{0}::{1}", 
        method.ReflectedType != null ? method.ReflectedType.Name : string.Empty,
        method.Name));
  }
}