Bagaimana cara mencetak jejak tumpukan penuh dalam pengecualian?

98

Misalnya, di satu tempat ...

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

... dan di tempat lain ...

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

Stacktrace yang saya cetak, hanya mulai dari a hingga b, tidak menyertakan stacktrace dalam dari WebException.

Bagaimana cara mencetak semua stacktrace ???

jojo
sumber
1
Perhatikan bahwa stacktrace untuk WebException yang berasal tidak akan dicetak karena Anda melontarkan pengecualian baru daripada membuang kembali WebException. Gunakan throw;sebagai pengganti throw new MyCustomException(...)jika Anda ingin mempertahankan (dan mengeluarkan) tumpukan pengecualian asli.
Beel

Jawaban:

174

Saya biasanya menggunakan metode .ToString () pada pengecualian untuk menyajikan informasi pengecualian lengkap (termasuk jejak tumpukan dalam) dalam teks:

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

Output sampel:

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
Justin
sumber
Baik sekali. Saya mencari cara sederhana untuk melakukannya dan ini dia. Beberapa perhatian kecil adalah itu tidak sedeksplisit jika Anda menggunakan objek exception.StackTrace (misalnya). Saya ingin tahu apakah ada cara yang lebih eksplisit untuk melakukan hal yang sama?
kode
4
Ketahuilah bahwa beberapa pustaka mengganti ToStringmetode dan mencetak pesan khusus alih-alih informasi lengkap (ini adalah praktik pengkodean yang buruk, jadi jangan pernah melakukannya)
Dinei
@P ரதீப் Saya gunakan ToStringsetiap kali saya yakin itu tidak ditimpa, dan menggunakan properti secara langsung sebaliknya (seperti jawaban Andrew Hare ).
Dinei
53

Gunakan fungsi seperti ini:

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

Kemudian Anda bisa menyebutnya seperti ini:

try
{
    // invoke code above
}
catch(MyCustomException we)
{
    Debug.Writeline(FlattenException(we));
}
Andrew Hare
sumber
13
Atau Anda bisa menggunakan ToString?
Justin
Saya menggunakan ToString dan menurut saya tidak masalah. Saya akan menggunakan solusi Andrew jika saya hanya menginginkan pengecualian internal terendah (dengan alasan sebenarnya) atau pengambilan serupa .. meskipun keduanya berfungsi :)
EeKay
Ini lebih fleksibel daripada hanya ToString, karena Anda dapat memilih apa yang dimasukkan ke dalam string itu. Mungkin saya hanya tertarik pada jejak tumpukan, belum tentu pesannya. Atau saya ingin itu sebagai Daftar <string> bukan satu string.
Zar Shardan
18

1. Buat Metode: Jika Anda meneruskan pengecualian Anda ke fungsi berikut, ini akan memberi Anda semua metode dan detail yang menjadi alasan pengecualian.

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. Metode Panggilan: Anda dapat memanggil metode seperti ini.

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

3. Dapatkan Hasilnya:

File: c:\MyProject\Program.cs, Method:MyFunction, LineNumber: 29  -->  
File: c:\MyProject\Program.cs, Method:Main, LineNumber: 16  --> 
Oguzhan KIRCALI
sumber
1
Cukup membantu. Saya telah membuat metode ekstensi berdasarkan contoh Anda. BTW, dalam kasus sejumlah besar iterasi Anda sebaiknya menggunakan StringBuilderkelas.
AlexMelw
2
Tautan Andrey sudah mati. Ini adalah tautan terkini untuk implementasinya: github.com/AndreyWD/EasySharp/blob/master/NHelpers/…
Christian Junk
Andrey terlihat profesional. Saya meletakkan perpustakaan Anda di kotak peralatan saya. Terima kasih. @AndreyWD
Oguzhan KIRCALI