Як надрукувати повний трас стека за винятком?


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(...)якщо ви хочете зберегти (і вивести) вихідний стек винятків.
Біл

Відповіді:


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 (наприклад). Цікаво, чи існує більш чіткий спосіб зробити те саме?
codea

4
Майте на увазі, що деякі бібліотеки замінюють ToStringметод і друкують власні повідомлення замість повної інформації (це погана практика кодування, тому не робіть цього ніколи)
Діней

@P ரதீப் Я використовую, ToStringколи впевнений, що він не перезаписаний, і використовую властивості безпосередньо в іншому випадку (як відповідь Ендрю Зайця ).
Діней

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 і думаю, що це нормально. Я б пішов із рішенням Ендрю, якщо я хочу лише найнижчий внутрішній виняток (з фактичною причиною) або подібний вибір. Хоча працює і те, і інше :)
EeKay

Це більш гнучко, ніж просто ToString, оскільки ви можете вибрати, що входить у цей рядок. Можливо, мене цікавлять лише сліди стека, не обов'язково повідомлення. Або я хочу, щоб це був список <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

2
Посилання Андрія було мертвим. Це поточне посилання на його реалізацію: github.com/AndreyWD/EasySharp/blob/master/NHelpers/…
Christian Junk,

Це виглядає професійно Андрій. Я помістив вашу бібліотеку до мого набору інструментів. Дякую. @AndreyWD
Oguzhan KIRCALI
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.