จะพิมพ์การติดตามสแต็กแบบเต็มได้อย่างไร?


101

ตัวอย่างเช่นในที่เดียว ...

//---------------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 เท่านั้นไม่รวม stacktrace ภายในจาก WebException

ฉันจะพิมพ์ stacktrace ทั้งหมดได้อย่างไร ???


1
โปรดสังเกตว่า stacktrace สำหรับ WebException ต้นทางจะไม่ถูกพิมพ์เนื่องจากคุณส่งข้อยกเว้นใหม่แทนที่จะโยน WebException ซ้ำ ใช้throw;แทนthrow new MyCustomException(...)ถ้าคุณต้องการรักษา (และเอาต์พุต) สแต็กข้อยกเว้นดั้งเดิม
Beel

คำตอบ:


180

ฉันมักจะใช้เมธอด. 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

ดีมาก. ฉันกำลังมองหาวิธีง่ายๆในการทำและนี่คือ ข้อกังวลเล็กน้อยคือมันไม่ชัดเจนมากเท่ากับว่าคุณใช้ข้อยกเว้นวัตถุ StackTrace (ตัวอย่าง) ฉันสงสัยว่ามีวิธีที่ชัดเจนกว่านี้ในการทำเช่นเดียวกันหรือไม่?
codea

5
โปรดทราบว่าห้องสมุดบางแทนที่ToStringวิธีการและพิมพ์ข้อความที่กำหนดเองแทนข้อมูลเต็มรูปแบบ (นี้คือการเข้ารหัสปฏิบัติไม่ดีจึงไม่ได้ทำอย่างนั้นเลยทีเดียว)
Dinei

@P ரதீப்ฉันใช้ToStringเมื่อใดก็ตามที่ฉันแน่ใจว่ามันไม่ได้ถูกเขียนทับและใช้คุณสมบัติโดยตรงเป็นอย่างอื่น (เช่นคำตอบของ Andrew Hare )
Dinei

ฉันโง่ที่ใช้exception.StackTraceและคิดว่ามันจะได้ผล
Kolob Canyon

55

ใช้ฟังก์ชันเช่นนี้:

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

15
หรือคุณสามารถใช้ToString?
จัสติน

ฉันใช้ ToString และคิดว่ามันใช้ได้ ฉันจะใช้วิธีแก้ปัญหาของ Andrew ถ้าฉันต้องการเพียงข้อยกเว้นภายในที่ต่ำที่สุด (พร้อมเหตุผลที่แท้จริง) หรือการเลือกที่คล้ายกัน .. ใช้ได้ทั้งสองอย่าง :)
EeKay

ซึ่งมีความยืดหยุ่นมากกว่าเพียงแค่ ToString เนื่องจากคุณสามารถเลือกสิ่งที่จะเข้าสู่สตริงนั้นได้ บางทีฉันสนใจแค่สแต็กเทรซเท่านั้นไม่จำเป็นต้องเป็นข้อความเสมอไป หรือฉันต้องการให้เป็น List <string> ไม่ใช่สตริงเดียว
Zar Shardan

แล้วข้อยกเว้นด้านในล่ะ?
Clark

19

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. Call Method:เรียก method แบบนี้ก็ได้

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
เป็นประโยชน์มาก ฉันได้สร้างวิธีการขยายตามตัวอย่างของคุณแล้ว BTW ในกรณีที่มีการทำซ้ำจำนวนมากคุณควรใช้StringBuilderคลาส
AlexMelw

2
Andreys link เสียชีวิตแล้ว นี่คือลิงค์ปัจจุบันไปยังการใช้งานของเขา: github.com/AndreyWD/EasySharp/blob/master/NHelpers/…
Christian Junk

ที่ดูเป็นมืออาชีพ Andrey ฉันใส่ห้องสมุดของคุณในกล่องเครื่องมือของฉัน ขอบคุณ. @AndreyWD
Oguzhan KIRCALI
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.