如何在异常中打印完整的堆栈跟踪?


98

例如,在一处...

//---------------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中的内部stacktrace。

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


1
请注意,不会打印原始WebException的stacktrace,因为您引发了新的异常,而不是重新引发了WebException。使用throw;替代的throw new MyCustomException(...),如果你想保留(输出)原始异常堆栈。
贝尔

Answers:


174

我通常对异常使用.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对象那样显式。我想知道是否有更明确的方法可以做到这一点?
编码

4
请注意,有些库会覆盖该ToString方法并打印自定义消息,而不是完整信息(这是一种不良的编码习惯,所以永远要这样做)
Dinei 2016年

@Pரதீப் ToString每当我确定它不会被覆盖时就使用它,否则直接使用属性(例如Andrew Hare的答案)。
Dinei

53

使用如下函数:

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

13
还是可以使用ToString
贾斯汀2010年

我正在使用ToString,认为还好。如果我只想要最低的内部异常(有实际原因)或类似的选择,我会选择安德鲁的解决方案。尽管这两者都
可行

这比ToString更灵活,因为您可以选择该字符串中的内容。也许我只对堆栈跟踪感兴趣,而不一定对消息感兴趣。或者我希望它作为List <string>而不是单个字符串。
Zar Shardan

18

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

1
很有帮助。我根据您的示例做了一个扩展方法。顺便说一句,在大量迭代的情况下,您最好使用StringBuilderclass。
AlexMelw

2
安德烈斯·林克死了。这是当前连接到他的实现:github.com/AndreyWD/EasySharp/blob/master/NHelpers/...
基督教垃圾

看起来很专业的安德烈。我将您的库放在工具箱中。谢谢。@AndreyWD
Oguzhan KIRCALI
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.