2008-09-09 18 views
50

Dans le cadre de la gestion des erreurs dans notre produit, nous souhaitons vider certaines informations de trace de la pile. Cependant, nous constatons que de nombreux utilisateurs prennent simplement une capture d'écran de la boîte de dialogue des messages d'erreur au lieu de nous envoyer une copie du rapport complet disponible dans le programme.Informations sur la trace de la pile d'impression à partir du C#

Une trace de pile .NET sur ma machine ressemble à ceci:

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 

J'ai cette question:

Le format semble être ceci:

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

Cependant, le à et dans mots-clés, je suppose que ceux-ci seront localisés s'ils s'exécutent, disons, un norvégien .NET runtime i Au lieu de l'anglais que j'ai installé.

Y a-t-il un moyen pour moi de séparer cette trace de pile d'une manière neutre, de sorte que je puisse afficher seulement le fichier et le numéro de ligne pour les entrées qui ont ceci?

En d'autres termes, je voudrais cette information du texte ci-dessus:

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

les conseils que vous pouvez donner vous sera utile.

+1

Je souhaite que quelqu'un aurait donné la réponse de l'analyse syntaxique pour ce que je travaille avec des chaînes journalisés des applications arbitraires et espérait vraiment avoir des détails à ce sujet.Étant donné que vous avez le contrôle de la source du StackTrace, vous avez en effet choisi la bonne réponse :) – TheXenocide

Répondre

70

Vous devriez être en mesure d'obtenir un objet StackTrace au lieu d'une chaîne en disant

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

Vous pouvez alors regarder les images vous-même sans compter sur la mise en forme du cadre.

Voir aussi: StackTrace reference

+0

Oooh, sympa, je ne le savais pas! Je vais certainement regarder ça. –

+0

En mode release, êtes-vous toujours en mesure d'obtenir une trace de pile d'une exception avec précision? – erdogany

+0

Je sérialise ** exception ** dans le fichier. 'SerializationHelper.Serialize (@" c: \ temp \ ConfigurationErrorsExceptions.ser ", ex);' Si je désérialise du fichier 'var exception = SerializationHelper.Deserialize (@" ConfigurationErrorsExceptions.ser ");' *** Trace *** est _not available_ 'var trace = new System.Diagnostics.StackTrace (exception Exception);' le ** FrameCount ** est 0 – Kiquenet

0

Comme alternative log4net, bien que potentiellement dangereux, m'a donné de meilleurs résultats que System.Diagnostics. Fondamentalement, dans log4net, vous avez une méthode pour les différents niveaux de journaux, chacun avec un paramètre Exception. Ainsi, lorsque vous passez la deuxième exception, elle imprime la trace de la pile vers l'appendeur que vous avez configuré.

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

La sortie, en fonction de la configuration, ressemble à quelque chose comme

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

Pourriez-vous clarifier ce que vous voulez dire à propos de log4net étant "potentiellement dangereux"? –

+0

Je ne sais pas exactement ce qu'Oglester voulait dire, mais je sais que stackoverflow.com a eu des problèmes de blocage car log4net enregistrait des exceptions dans une base de données. Je n'ai pas personnellement eu de problèmes, mais je reste simple et je m'en tiens aux fichiers texte. –

+0

Si vous ne gérez pas correctement vos références, vous vous retrouverez avec une fuite de mémoire. Le site web sur lequel j'ai travaillé tout à l'heure utilise largement log4net (fichiers roulants). Parce que le fichier de références log4net (non sécurisé), vous devez être sûr de garder les références log4net nettoyé ou à un minimum. –

27

Voici le code que j'utilise pour le faire sans exception

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

On pourrait penser que cela serait construit dans la fonctionnalité quelque part puisque le gestionnaire d'exception le fait nativement. –

18

Juste pour ceci une copie de copier-coller de 15 secondes:

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

(fonction de la réponse Lindholm)

+3

Merci pour cela. Notez que vous pouvez utiliser sb.AppendLine (...) pour éviter le codage en dur du caractère de fin de ligne spécifique. –

+0

vrai. actualisé... –

8

Ou il y a même version plus courte ..

Console.Write(exception.StackTrace);