2008-09-09 14 views
50

Como parte de algún error en el manejo de nuestro producto, nos gustaría descargar alguna información de seguimiento de la pila. Sin embargo, experimentamos que muchos usuarios simplemente tomarán una captura de pantalla del cuadro de diálogo de mensaje de error en lugar de enviarnos una copia del informe completo disponible del programa, y ​​por lo tanto me gustaría hacer que haya información mínima de seguimiento de pila disponible en este diálogo.Imprimir la información de seguimiento de la pila de C#

Un .NET seguimiento de la pila en mi máquina se parece a esto:

at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath) 
at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy) 
at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, FileOptions options) 
at System.IO.StreamReader..ctor(String path, Encoding encoding, Boolean detectEncodingFromByteOrderMarks, Int32 bufferSize) 
at System.IO.StreamReader..ctor(String path) 
at LVKWinFormsSandbox.MainForm.button1_Click(Object sender, EventArgs e) in C:\Dev\VS.NET\Gatsoft\LVKWinFormsSandbox\MainForm.cs:line 36 

tengo esta pregunta: ¿

El formato parece ser la siguiente:

at <class/method> [in file:line ##] 

Sin embargo, el en y en palabras clave, supongo que estas serán localizadas si se ejecutan, por ejemplo, un tiempo de ejecución .NET noruego en lugar del inglés que tengo instalado

¿Hay alguna manera de separar este trazado de la pila de una manera neutral en cuanto al idioma, de modo que pueda mostrar solo el archivo y el número de línea para las entradas que tienen esto?

En otras palabras, me gustaría que esta información del texto anterior:

C:\Dev\VS.NET\Gatsoft\LVKWinFormsSandbox\MainForm.cs:line 36 

Cualquier consejo que puede dar será útil.

+1

Me gustaría que alguien hubiera dado la respuesta de análisis sintáctico para esto como yo estoy trabajando con cadenas registrados por parte de aplicaciones arbitrarias y realmente esperaba obtener algunos detalles sobre esto.Dado que tienes el control de la fuente de StackTrace, sí has ​​elegido la respuesta correcta :) – TheXenocide

Respuesta

70

Usted debe ser capaz de obtener un objeto StackTrace lugar de una cadena diciendo

var trace = new System.Diagnostics.StackTrace(exception); 

A continuación, puede ver las tramas a sí mismo sin depender de formato del marco.

Consulte también: StackTrace reference

+0

¡Oooh, qué bien, no lo sabía! Definitivamente voy a investigar esto. –

+0

¿En el modo de lanzamiento todavía puede obtener el rastro de pila de una excepción con precisión? – erdogany

+0

serializo ** excepción ** en el archivo. 'SerializationHelper.Serialize (@" c: \ temp \ ConfigurationErrorsExceptions.ser ", ex);' Si deserializo del archivo 'var exception = SerializationHelper.Deserialize (@" ConfigurationErrorsExceptions.ser ");' *** Trace *** is _not available_ 'var trace = new System.Diagnostics.StackTrace (excepción como Exception);' the ** FrameCount ** es 0 – Kiquenet

0

Como alternativa, log4net, aunque potencialmente peligroso, me ha dado mejores resultados que System.Diagnostics. Básicamente en log4net, tiene un método para los diversos niveles de registro, cada uno con un parámetro de excepción. Por lo tanto, cuando pase la segunda excepción, imprimirá el seguimiento de la pila a cualquier apéndice que haya configurado.

ejemplo: Logger.Error("Danger!!!", myException);

La salida, dependiendo de la configuración, se ve algo así como

System.ApplicationException: Something went wrong. 
    at Adapter.WriteToFile(OleDbCommand cmd) in C:\Adapter.vb:line 35 
    at Adapter.GetDistributionDocument(Int32 id) in C:\Adapter.vb:line 181 
    ... 
+0

¿Podría aclarar qué quiere decir con que log4net es "potencialmente peligroso"? –

+0

No sé con certeza a qué se refería Oglester, pero sé que stackoverflow.com tuvo algunos problemas de interbloqueo porque log4net estaba registrando excepciones en una base de datos. Personalmente no he tenido ningún problema, pero lo mantengo simple y me apego a los archivos de texto. –

+0

Si no administra sus referencias correctamente, terminará con una pérdida de memoria. El sitio web en el que trabajé hace un tiempo usa log4net extensamente (archivos rodantes). Debido a que el archivo de referencias de log4net (inseguro), debe asegurarse de mantener limpiadas las referencias de log4net o al mínimo. –

27

Aquí está el código que utilizo para hacer esto sin una excepción

public static void LogStack() 
{ 
    var trace = new System.Diagnostics.StackTrace(); 
    foreach (var frame in trace.GetFrames()) 
    { 
    var method = frame.GetMethod(); 
    if (method.Name.Equals("LogStack")) continue; 
    Log.Debug(string.Format("{0}::{1}", 
     method.ReflectedType != null ? method.ReflectedType.Name : string.Empty, 
     method.Name)); 
    } 
} 
+0

Podría pensar que esto se construiría en la funcionalidad en alguna parte ya que el manejador de excepciones lo hace de forma nativa. –

18

Sólo para hacer esto una respuesta copy-paste de 15 segundos:

static public string StackTraceToString() 
{ 
    StringBuilder sb = new StringBuilder(256); 
    var frames = new System.Diagnostics.StackTrace().GetFrames(); 
    for (int i = 1; i < frames.Length; i++) /* Ignore current StackTraceToString method...*/ 
    { 
     var currFrame = frames[i]; 
     var method = currFrame.GetMethod(); 
     sb.AppendLine(string.Format("{0}:{1}",      
      method.ReflectedType != null ? method.ReflectedType.Name : string.Empty, 
      method.Name)); 
    } 
    return sb.ToString(); 
} 

(basado en la respuesta Lindholm)

+3

Gracias por eso. Tenga en cuenta que puede usar sb.AppendLine (...) para evitar codificar el carácter específico de fin de línea. –

+0

cierto. actualizado... –

8

O hay versión aún más corta ..

Console.Write(exception.StackTrace); 
Cuestiones relacionadas