从C#打印堆栈跟踪信息

时间:2022-10-30 21:31:55

As part of some error handling in our product, we'd like to dump some stack trace information. However, we experience that many users will simply take a screenshot of the error message dialog instead of sending us a copy of the full report available from the program, and thus I'd like to make some minimal stack trace information available in this dialog.

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

A .NET stack trace on my machine looks like this:

我机器上的.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

I have this question:

我有这个问题:

The format looks to be this:

格式看起来是这样的:

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

However, the at and in keywords, I assume these will be localized if they run, say, a norwegian .NET runtime instead of the english one I have installed.

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

Is there any way for me to pick apart this stack trace in a language-neutral manner, so that I can display only the file and line number for those entries that have this?

有没有办法让我以语言中立的方式分离这个堆栈跟踪,这样我才能显示那些具有此条目的条目的文件和行号?

In other words, I'd like this information from the above text:

换句话说,我想从上面的文字中获得这些信息:

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

Any advice you can give will be helpful.

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

5 个解决方案

#1


70  

You should be able to get a StackTrace object instead of a string by saying

您应该能够通过说明获取StackTrace对象而不是字符串

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

You can then look at the frames yourself without relying on the framework's formatting.

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

See also: StackTrace reference

另请参见:StackTrace参考

#2


27  

Here is the code I use to do this without an exception

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

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

#3


18  

Just to make this a 15 sec copy-paste answer:

只需将这个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();
}

(based on Lindholm answer)

(根据Lindholm的回答)

#4


8  

Or there is even shorter version..

或者甚至更短的版本..

Console.Write(exception.StackTrace);

#5


0  

As alternative, log4net, though potentially dangerous, has given me better results than System.Diagnostics. Basically in log4net, you have a method for the various log levels, each with an Exception parameter. So, when you pass the second exception, it will print the stack trace to whichever appender you have configured.

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

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

示例:Logger.Error(“Danger !!!”,myException);

The output, depending on configuration, looks something like

根据配置,输出看起来像

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

#1


70  

You should be able to get a StackTrace object instead of a string by saying

您应该能够通过说明获取StackTrace对象而不是字符串

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

You can then look at the frames yourself without relying on the framework's formatting.

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

See also: StackTrace reference

另请参见:StackTrace参考

#2


27  

Here is the code I use to do this without an exception

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

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

#3


18  

Just to make this a 15 sec copy-paste answer:

只需将这个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();
}

(based on Lindholm answer)

(根据Lindholm的回答)

#4


8  

Or there is even shorter version..

或者甚至更短的版本..

Console.Write(exception.StackTrace);

#5


0  

As alternative, log4net, though potentially dangerous, has given me better results than System.Diagnostics. Basically in log4net, you have a method for the various log levels, each with an Exception parameter. So, when you pass the second exception, it will print the stack trace to whichever appender you have configured.

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

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

示例:Logger.Error(“Danger !!!”,myException);

The output, depending on configuration, looks something like

根据配置,输出看起来像

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