【问题标题】:How to print full stack trace in exception?如何在异常中打印完整的堆栈跟踪?
【发布时间】:2011-05-15 10:16:01
【问题描述】:

例如,在一个地方...

//---------------a
try
{
    // some network call
}
catch(WebException we)
{
    throw new MyCustomException("some message ....", we);
}

...在另一个地方...

//--------------b
try
{
    // invoke code above
}
catch(MyCustomException we)
{
    Debug.Writeline(we.stacktrace);   // <----------------
}

我打印的stacktrace,它只从a开始到b, 它不包括来自 WebException 的内部堆栈跟踪。

如何打印所有的堆栈跟踪???

【问题讨论】:

  • 请注意,不会打印原始 WebException 的堆栈跟踪,因为您抛出了新异常而不是重新抛出 WebException。如果要保留(并输出)原始异常堆栈,请使用 throw; 代替 throw new MyCustomException(...)

标签: c# exception-handling stack-trace


【解决方案1】:

我通常在异常上使用.ToString() 方法以文本形式呈现完整的异常信息(包括内部堆栈跟踪):

catch (MyCustomException ex)
{
    Debug.WriteLine(ex.ToString());
}

样本输出:

ConsoleApplication1.MyCustomException: some message .... ---> System.Exception: Oh noes!
   at ConsoleApplication1.SomeObject.OtherMethod() in C:\ConsoleApplication1\SomeObject.cs:line 24
   at ConsoleApplication1.SomeObject..ctor() in C:\ConsoleApplication1\SomeObject.cs:line 14
   --- End of inner exception stack trace ---
   at ConsoleApplication1.SomeObject..ctor() in C:\ConsoleApplication1\SomeObject.cs:line 18
   at ConsoleApplication1.Program.DoSomething() in C:\ConsoleApplication1\Program.cs:line 23
   at ConsoleApplication1.Program.Main(String[] args) in C:\ConsoleApplication1\Program.cs:line 13

【讨论】:

  • 非常好。我一直在寻找一种简单的方法来做到这一点,就在这里。一些小问题是它不像您使用 exception.StackTrace 对象那样明确(例如)。我想知道是否有更明确的方法可以做到这一点?
  • 请注意,某些库会覆盖 ToString 方法并打印自定义消息而不是完整信息(这是一种糟糕的编码习惯,所以不要这样做,永远)
  • @Pரதீப் 只要我确定它没有被覆盖,我就使用ToString,否则直接使用属性(例如Andrew Hare's answer)。
  • 愚蠢的我使用 exception.StackTrace 并认为它会起作用
【解决方案2】:

使用这样的函数:

    public static string FlattenException(Exception exception)
    {
        var stringBuilder = new StringBuilder();

        while (exception != null)
        {
            stringBuilder.AppendLine(exception.Message);
            stringBuilder.AppendLine(exception.StackTrace);

            exception = exception.InnerException;
        }

        return stringBuilder.ToString();
    }

那么你可以这样称呼它:

try
{
    // invoke code above
}
catch(MyCustomException we)
{
    Debug.Writeline(FlattenException(we));
}

【讨论】:

  • 或者你可以使用ToString?
  • 我正在使用 ToString 并认为它很好。如果我只想要最低的内部异常(有实际原因)或类似的选择,我会选择 Andrew 的解决方案。但两者都适用:)
  • 这比 ToString 更灵活,因为您可以选择该字符串的内容。也许我只对堆栈跟踪感兴趣,不一定对消息感兴趣。或者我希望它作为 List 而不是单个字符串。
  • 内部异常呢?
  • @Clark 最初(在 .NET Framework 2.0 到 3.5 中)Exception.ToString() 没有输出 InnerException(或 AggregateException.InnerExceptions)的详细信息,但我相信自从 .NET Framework 4.0(其中 发布日期这个答案,因为它在 2010 年末 IIRC 中出现)确实ToString() 的输出中包含InnerException 对象图。
【解决方案3】:

1.创建方法: 如果您将异常传递给以下函数,它将为您提供异常原因的所有方法和详细信息。

public string GetAllFootprints(Exception x)
{
        var st = new StackTrace(x, true);
        var frames = st.GetFrames();
        var traceString = new StringBuilder();

        foreach (var frame in frames)
        {
            if (frame.GetFileLineNumber() < 1)
                continue;

            traceString.Append("File: " + frame.GetFileName());
            traceString.Append(", Method:" + frame.GetMethod().Name);
            traceString.Append(", LineNumber: " + frame.GetFileLineNumber());
            traceString.Append("  -->  ");
        }

        return traceString.ToString();
}

2。调用方法:可以这样调用方法。

try
{
    // code part which you want to catch exception on it
}
catch(Exception ex)
{
    Debug.Writeline(GetAllFootprints(ex));
}

3.获取结果:

File: c:\MyProject\Program.cs, Method:MyFunction, LineNumber: 29  -->  
File: c:\MyProject\Program.cs, Method:Main, LineNumber: 16  --> 

【讨论】:

  • 很有帮助。我根据您的示例制作了extension method。顺便说一句,在大量迭代的情况下,您最好使用StringBuilder 类。
  • Andreys 链接已失效。这是他的实现的当前链接:github.com/AndreyWD/EasySharp/blob/master/NHelpers/…
  • 看起来很专业的安德烈。我把你的图书馆放在我的工具箱里。谢谢。 @AndreyWD
【解决方案4】:

推荐使用LINQPad相关的nuget包,然后可以使用exceptionInstance.Dump()

对于 .NET 核心:

  • 安装LINQPad.Runtime

适用于 .NET 框架 4 等

  • 安装LINQPad

示例代码:

using System;
using LINQPad;

namespace csharp_Dump_test
{
    public class Program
    {
        public static void Main()
        {
            try
            {
                dosome();
            }
            catch (Exception ex)
            {
                ex.Dump();
            }
        }

        private static void dosome()
        {
            throw new Exception("Unable.");
        }
    }
}

运行结果:

LinqPad nuget 包是打印异常堆栈信息的最棒的工具。 希望对你有帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-08-06
    • 1970-01-01
    • 1970-01-01
    • 2012-09-04
    • 1970-01-01
    • 2011-01-18
    • 2011-12-12
    • 1970-01-01
    相关资源
    最近更新 更多