例外で完全なスタックトレースを印刷するにはどうすればよいですか?


97

たとえば、ある場所で...

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

私が出力するスタックトレースは、aからbまでで始まり、WebExceptionからの内部スタックトレースは含まれていません。

すべてのスタックトレースを出力するにはどうすればよいですか?


1
WebExceptionを再スローするのではなく、新しい例外をスローしたため、元のWebExceptionのスタックトレースは出力されないことに注意してください。元の例外スタックを保持(および出力)する場合throw;は、代わりに使用しthrow new MyCustomException(...)ます。
Beel

回答:


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オブジェクトを使用する場合ほど明示的ではありません。同じことをするためのより明確な方法があるのだろうか?
コデア2014年

4
一部のライブラリはToStringメソッドをオーバーライドし、完全な情報の代わりにカスタムメッセージを出力することに注意してください(これは
不適切

@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か?
ジャスティン

私はToStringを使用していますが、問題ないと思います。最低の内部例外(実際の理由による)または同様のピッキングのみが必要な場合は、Andrewのソリューションを使用します。ただし、両方とも機能します。)
EeKay

これは、文字列に何を入れるかを選択できるため、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
かなり役に立ちました。私はあなたの例に基づいて拡張メソッドを作りました。ところで、反復が多い場合は、StringBuilderクラスを使用することをお勧めします。
AlexMelw 2017

2
Andreysリンクは死んでいた。これは彼の実装への現在のリンクです:github.com/AndreyWD/EasySharp/blob/master/NHelpers/…–
クリスチャンジャンク

それはプロのアンドレイに見えます。ライブラリをツールボックスに入れました。ありがとう。@AndreyWD
Oguzhan KIRCALI 2018年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.