126 votes

Comment imprimer la trace complète de la pile dans une exception ?

Par exemple, à un endroit...

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

...et dans un autre endroit...

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

Le suivi de pile que j'imprime ne commence que de a à b, il n'inclut pas la trace interne de la WebException.

Comment puis-je imprimer toutes les traces de la pile ???

3 votes

Notez que la trace de la pile de la WebException d'origine ne sera pas imprimée parce que vous avez lancé une nouvelle exception au lieu de relancer la WebException. Utilisez throw; à la place de throw new MyCustomException(...) si vous voulez préserver (et sortir) la pile d'exceptions originale.

230voto

Justin Points 42106

J'utilise généralement le .ToString() sur les exceptions pour présenter les informations complètes sur les exceptions (y compris la trace de la pile interne) dans le texte :

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

Exemple de sortie :

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

0 votes

Très bien. Je cherchais un moyen simple de le faire et le voici. Un petit souci est que ce n'est pas aussi explicite que si vous utilisez l'objet exception.StackTrace (par exemple). Je me demande s'il existe un moyen plus explicite de faire la même chose ?

7 votes

Sachez que certaines bibliothèques remplacent l'option ToString et d'imprimer des messages personnalisés au lieu de l'information complète (il s'agit d'une mauvaise pratique de codage, donc ne faites pas de no faire ça, jamais)

0 votes

@P J'utilise ToString chaque fois que je suis sûr qu'il n'est pas écrasé, et utiliser les propriétés directement sinon (comme La réponse d'Andrew Hare ).

63voto

Andrew Hare Points 159332

Utilisez une fonction comme celle-ci :

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

Alors vous pouvez l'appeler comme ceci :

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

16 votes

Ou vous pouvez utiliser ToString ?

0 votes

J'utilise le ToString et je pense que c'est bien. J'opterais pour la solution d'Andrew si je ne voulais que l'exception interne la plus basse (avec la raison réelle) ou une sélection similaire mais les deux fonctionnent :)

1 votes

C'est plus souple que ToString, car vous pouvez choisir ce que contient cette chaîne. Je ne suis peut-être intéressé que par les traces de la pile, pas nécessairement par les messages. Ou bien je veux que ce soit une liste<string> et non une seule chaîne.

24voto

Oguzhan KIRCALI Points 194

1. Créez la méthode : Si vous passez votre exception à la fonction suivante, elle vous donnera toutes les méthodes et détails qui sont les raisons de l'exception.

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. Méthode d'appel : Vous pouvez appeler la méthode comme ceci.

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

3. Obtenez le résultat :

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

2voto

Bravo Yeung Points 376

Recommandez l'utilisation de LINQPad related nuget vous pouvez alors utiliser exceptionInstance.Dump() .

enter image description here

Pour .NET core :

  • Installer LINQPad.Runtime

Pour .NET framework 4 etc.

  • Installer LINQPad

Exemple de code :

using System;
using LINQPad;

namespace csharp_Dump_test
{
    public class Program
    {
        public static void Main()
        {
            try
            {
                dosome();
            }
            catch (Exception ex)
            {
                ex.Dump();
            }
        }

        private static void dosome()
        {
            throw new Exception("Unable.");
        }
    }
}

Résultat de la course : enter image description here

Le paquet nuget LinqPad est l'outil le plus génial pour imprimer les informations sur la pile des exceptions. Puisse-t-il vous être utile.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X