从 C 打印堆栈跟踪信息#

Print stack trace information from C#

提问人:Lasse V. Karlsen 提问时间:9/9/2008 最后编辑:Sergio AcostaLasse V. Karlsen 更新时间:11/17/2012 访问量:49184

问:

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

我的计算机上的 .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 ##]

但是,如果 atin 关键字运行挪威语 .NET 运行时而不是我安装的英语运行时,我认为它们将被本地化。

有没有办法让我以与语言无关的方式分离此堆栈跟踪,以便我可以仅显示具有此跟踪的条目的文件和行号?

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

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

您能提供的任何建议都会有所帮助。

C# 分析 错误处理 堆栈跟踪

评论

1赞 TheXenocide 9/18/2012
我希望有人能给出解析答案,因为我正在处理来自任意应用程序的记录字符串,并且真的希望得到一些细节。鉴于您可以控制 StackTrace 的源代码,您确实选择了正确的答案,但:)

答:

72赞 Curt Hagenlocher 9/9/2008 #1

您应该能够通过以下命令获取 StackTrace 对象而不是字符串

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

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

另请参阅:StackTrace 参考

评论

0赞 Lasse V. Karlsen 9/9/2008
哦,太好了,我不知道!我一定会调查这个。
0赞 yusuf 3/16/2009
在发布模式下,您仍然能够精确地获取异常的堆栈跟踪吗?
0赞 Kiquenet 10/13/2015
我在文件中序列化异常。 如果我从文件反序列化,则 Trace 不可用则 FrameCount 为 0SerializationHelper.Serialize(@"c:\temp\ConfigurationErrorsExceptions.ser", ex);var exception = SerializationHelper.Deserialize(@"ConfigurationErrorsExceptions.ser");var trace = new System.Diagnostics.StackTrace(exception as Exception);
1赞 oglester 9/9/2008 #2

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

例: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
   ...

评论

0赞 Scott Lawrence 9/9/2008
您能澄清一下您对 log4net 的“潜在危险”是什么意思吗?
0赞 Don Kirkby 9/17/2008
我不确定 Oglester 是什么意思,但我知道 stackoverflow.com 有一些死锁问题,因为 log4net 正在记录数据库的异常。我个人没有遇到任何问题,但我保持简单并坚持滚动文本文件。
0赞 oglester 10/2/2008
如果不能正确管理引用,则最终会导致内存泄漏。我前段时间工作的网站广泛使用log4net(滚动文件)。由于 log4net 引用文件(不安全),因此必须确保将 log4net 引用清理到最低限度。
29赞 Lindholm 8/6/2009 #3

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

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));
  }
}

评论

0赞 Denise Skidmore 3/31/2015
您可能会认为这将内置在某处的功能中,因为异常处理程序本身会这样做。
19赞 Hertzel Guinness 5/22/2011 #4

只是为了使这成为一个 15 秒的复制粘贴答案:

static public string StackTraceToString()
{
    StringBuilder sb = new StringBuilder(256);
    var frames = new System.Diagnostics.StackTrace().GetFrames();
    for (int i = 1; i < frames.Length; i++) /* Ignore current StackTraceToString method...*/
    {
        var currFrame = frames[i];
        var method = currFrame.GetMethod();
        sb.AppendLine(string.Format("{0}:{1}",                    
            method.ReflectedType != null ? method.ReflectedType.Name : string.Empty,
            method.Name));
    }
    return sb.ToString();
}

(基于Lindholm的回答)

评论

3赞 Lee Oades 5/30/2012
谢谢你。请注意,您可以使用 sb.AppendLine(...) 以避免对特定的行尾字符进行硬编码。
9赞 Aftershock 1/9/2012 #5

或者还有更短的版本..

Console.Write(exception.StackTrace);