¿Cómo imprimir el seguimiento de pila completa en excepción?

97

Por ejemplo, en un lugar ...

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

... y en otro lugar ...

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

El stacktrace que imprimo, solo comienza de aab, no incluye el stacktrace interno de WebException.

¿Cómo puedo imprimir todo el stacktrace?

jojo
fuente
1
Tenga en cuenta que el seguimiento de pila para la WebException de origen no se imprimirá porque lanzó una nueva excepción en lugar de volver a lanzar la WebException. Úselo throw;en lugar de throw new MyCustomException(...)si desea conservar (y generar) la pila de excepciones original.
Beel

Respuestas:

174

Normalmente uso el método .ToString () en excepciones para presentar la información completa de la excepción (incluido el seguimiento de la pila interna) en el texto:

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

Salida de muestra:

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
fuente
Muy bien. Estaba buscando una forma sencilla de hacerlo y aquí está. Una pequeña preocupación es que no es tan explícito como si usa el objeto exception.StackTrace (por ejemplo). Me pregunto si hay una forma más explícita de hacer lo mismo.
codea
4
Tenga en cuenta que algunas bibliotecas anulan el ToStringmétodo e imprimen mensajes personalizados en lugar de la información completa (esta es una mala práctica de codificación, así que no haga eso, nunca)
Dinei
@P ரதீப் Lo uso ToStringsiempre que estoy seguro de que no se sobrescribe, y uso las propiedades directamente de lo contrario (como la respuesta de Andrew Hare ).
Dinei
53

Usa una función como esta:

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

Entonces puedes llamarlo así:

try
{
    // invoke code above
}
catch(MyCustomException we)
{
    Debug.Writeline(FlattenException(we));
}
Andrew Hare
fuente
13
¿O puedes usar ToString?
Justin
Estoy usando ToString y creo que está bien. Iría con la solución de Andrew si solo quiero la excepción interna más baja (con la razón real) o una selección similar ... aunque funciona en ambos :)
EeKay
Esto es más flexible que solo ToString, porque puede elegir lo que entra en esa cadena. Tal vez solo me interesen los seguimientos de la pila, no necesariamente los mensajes. O lo quiero como una List <string>, no como una sola cadena.
Zar Shardan
18

1. Crear método: si pasa su excepción a la siguiente función, le dará todos los métodos y detalles que son los motivos de la excepción.

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. Llamar al método: puede llamar al método de esta manera.

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

3. Obtenga el resultado:

File: c:\MyProject\Program.cs, Method:MyFunction, LineNumber: 29  -->  
File: c:\MyProject\Program.cs, Method:Main, LineNumber: 16  --> 
Oguzhan KIRCALI
fuente
1
Bastante util. Hice un método de extensión basado en tu ejemplo. Por cierto, en caso de una gran cantidad de iteraciones, será mejor que uses StringBuilderclass.
AlexMelw
2
El enlace de Andreys estaba muerto. Este es el enlace actual a su implementación: github.com/AndreyWD/EasySharp/blob/master/NHelpers/…
Christian Junk
Eso parece un Andrey profesional. Pongo tu biblioteca en mi caja de herramientas. Gracias. @AndreyWD
Oguzhan KIRCALI