Làm thế nào để in dấu vết ngăn xếp đầy đủ trong ngoại lệ?


97

Ví dụ, ở một nơi ...

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

... và ở một nơi khác ...

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

Stacktrace tôi in, nó chỉ bắt đầu từ a đến b, nó không bao gồm stacktrace bên trong từ WebException.

Làm thế nào tôi có thể in tất cả các stacktrace ???


1
Lưu ý rằng stacktrace cho WebException ban đầu sẽ không được in bởi vì bạn đã ném một ngoại lệ mới thay vì ném lại WebException. Sử dụng throw;thay cho throw new MyCustomException(...)nếu bạn muốn bảo toàn (và xuất) ngăn xếp ngoại lệ ban đầu.
Beel

Câu trả lời:


174

Tôi thường sử dụng phương thức .ToString () trên các ngoại lệ để trình bày đầy đủ thông tin ngoại lệ (bao gồm cả dấu vết ngăn xếp bên trong) trong văn bản:

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

Đầu ra mẫu:

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

Rất tốt. Tôi đã tìm kiếm một cách đơn giản để làm điều đó và nó đây. Một số mối quan tâm nhỏ là nó không rõ ràng nhiều như khi bạn sử dụng đối tượng exception.StackTrace (ví dụ). Tôi tự hỏi nếu có một cách rõ ràng hơn để làm điều tương tự?
codea

4
Hãy nhận biết rằng một số thư viện ghi đè lên các ToStringphương pháp và in thông điệp tùy chỉnh thay vì những thông tin đầy đủ (điều này là một thực hành mã hóa xấu, do đó, không làm điều đó, bao giờ)
Dinei

@P ரதீப் Tôi sử dụng ToStringbất cứ khi nào tôi chắc chắn rằng nó không bị ghi đè và sử dụng trực tiếp các thuộc tính nếu không (như câu trả lời của Andrew Hare ).
Dinei

53

Sử dụng một chức năng như thế này:

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

Sau đó, bạn có thể gọi nó như thế này:

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

13
Hoặc bạn có thể sử dụng ToString?
Justin

Tôi đang sử dụng ToString và nghĩ rằng nó ổn. Tôi sẽ đi với giải pháp của Andrew nếu tôi chỉ muốn ngoại lệ bên trong thấp nhất (với lý do thực tế) hoặc chọn tương tự .. mặc dù hoạt động cả hai :)
EeKay

Điều này linh hoạt hơn chỉ ToString, vì bạn có thể chọn những gì đi vào chuỗi đó. Có lẽ tôi chỉ quan tâm đến dấu vết ngăn xếp, không nhất thiết phải là tin nhắn. Hoặc tôi muốn nó dưới dạng Danh sách <chuỗi> không phải là một chuỗi đơn lẻ.
Zar Shardan

18

1. Tạo Phương thức: Nếu bạn chuyển ngoại lệ của mình cho hàm sau, nó sẽ cung cấp cho bạn tất cả các phương thức và chi tiết là lý do của ngoại lệ.

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. Phương thức Gọi: Bạn có thể gọi phương thức như thế này.

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

3. Nhận kết quả:

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

1
Khá hữu ich. Tôi đã tạo một phương pháp mở rộng dựa trên ví dụ của bạn. BTW, trong trường hợp có nhiều lần lặp lại, bạn nên sử dụng StringBuilderlớp.
AlexMelw

2
Liên kết Andreys đã chết. Đây là liên kết hiện tại đến việc triển khai của anh ấy: github.com/AndreyWD/EasySharp/blob/master/NHelpers/…
Christian Junk

Trông Andrey thật chuyên nghiệp. Tôi đặt thư viện của bạn trong hộp công cụ của tôi. Cảm ơn. @AndreyWD
Oguzhan KIRCALI
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.