Quelle est la bonne façon de montrer ma InnerException
complète?.
J'ai trouvé que certaines de mes InnerExceptions ont une autre InnerException
et cela va assez profond.
InnerException.ToString()
fera-t-il le travail à ma place ou dois-je parcourir la InnerExceptions
et créer une String
avec StringBuilder
?
Vous pouvez simplement imprimer exception.ToString()
- qui inclura également le texte intégral pour tous les InnerException
s imbriqués.
Il suffit d'utiliser exception.ToString()
http://msdn.Microsoft.com/en-us/library/system.exception.tostring.aspx
L'implémentation par défaut de ToString obtient le nom de la classe qui a levé l'exception actuelle, le message, le résultat de l'appel de ToString sur l'exception interne et le résultat de l'appel de Environment.StackTrace. Si l'un de ces membres est null, sa valeur n'est pas incluse dans la chaîne renvoyée.
S'il n'y a pas de message d'erreur ou s'il s'agit d'une chaîne vide (""), aucun message d'erreur n'est renvoyé. Le nom de l'exception interne et la trace de la pile ne sont renvoyés que s'ils ne sont pas nuls.
exception.ToString () appellera également .ToString () sur l'exception interne de cette exception, et ainsi de suite ...
J'ai l'habitude de faire comme ça pour enlever la plupart du bruit:
void LogException(Exception error) {
Exception realerror = error;
while (realerror.InnerException != null)
realerror = realerror.InnerException;
Console.WriteLine(realerror.ToString())
}
Edit: / J'ai oublié cette réponse et je suis surpris que personne ne dise que vous pouvez simplement faire
void LogException(Exception error) {
Console.WriteLine(error.GetBaseException().ToString())
}
La réponse de @ Jon est la meilleure solution lorsque vous souhaitez des détails complets (tous les messages et la trace de la pile) et celle recommandée.
Cependant, il peut arriver que vous souhaitiez uniquement les messages internes, et j'utilise la méthode d'extension suivante:
public static class ExceptionExtensions
{
public static string GetFullMessage(this Exception ex)
{
return ex.InnerException == null
? ex.Message
: ex.Message + " --> " + ex.InnerException.GetFullMessage();
}
}
J'utilise souvent cette méthode lorsque différents écouteurs effectuent le traçage et la journalisation et que je souhaite avoir différentes vues sur eux. De cette façon, je peux avoir un auditeur qui envoie toute l’erreur avec trace de pile par courrier électronique à l’équipe de développement pour le débogage à l’aide de la méthode .ToString()
et un qui écrit un fichier de connexion avec l’historique de toutes les erreurs survenues chaque jour sans trace de pile. avec la méthode .GetFullMessage()
.
Pour imprimer simplement la partie Message
s des exceptions profondes, vous pouvez faire quelque chose comme ceci:
public static string ToFormattedString(this Exception exception)
{
IEnumerable<string> messages = exception
.GetAllExceptions()
.Where(e => !String.IsNullOrWhiteSpace(e.Message))
.Select(e => e.Message.Trim());
string flattened = String.Join(Environment.NewLine, messages); // <-- the separator here
return flattened;
}
public static IEnumerable<Exception> GetAllExceptions(this Exception exception)
{
yield return exception;
if (exception is AggregateException aggrEx)
{
foreach (Exception innerEx in aggrEx.InnerExceptions.SelectMany(e => e.GetAllExceptions()))
{
yield return innerEx;
}
}
else if (exception.InnerException != null)
{
foreach (Exception innerEx in exception.InnerException.GetAllExceptions())
{
yield return innerEx;
}
}
}
Cela passe de manière récursive dans toutes les exceptions internes (y compris le cas de AggregateException
s) pour imprimer toutes les propriétés Message
qui y sont contenues, délimitées par un saut de ligne.
Par exemple.
var outerAggrEx = new AggregateException(
"Outer aggr ex occurred.",
new AggregateException("Inner aggr ex.", new FormatException("Number isn't in correct format.")),
new IOException("Unauthorized file access.", new SecurityException("Not administrator.")));
Console.WriteLine(outerAggrEx.ToFormattedString());
Aggr ex externe s'est produit.
Aggr intérieure ex.
Le numéro n'est pas au format correct.
Accès au fichier non autorisé.
Pas administrateur.
Vous devrez écouter les autres propriétés Exception / propriétés pour plus de détails. Par exemple Data
aura des informations. Vous pourriez faire:
foreach (DictionaryEntry kvp in exception.Data)
Pour obtenir toutes les propriétés dérivées (pas sur la classe Exception
de base), vous pouvez faire:
exception
.GetType()
.GetProperties()
.Where(p => p.CanRead)
.Where(p => p.GetMethod.GetBaseDefinition().DeclaringType != typeof(Exception));
Si vous souhaitez des informations sur toutes les exceptions, utilisez exception.ToString()
. Il collectera des données de toutes les exceptions internes.
Si vous ne voulez que l'exception d'origine, utilisez exception.GetBaseException().ToString()
. Cela vous donnera la première exception, par exemple. l'exception interne la plus profonde ou l'exception actuelle s'il n'y a pas d'exception interne.
Exemple:
try {
Exception ex1 = new Exception( "Original" );
Exception ex2 = new Exception( "Second", ex1 );
Exception ex3 = new Exception( "Third", ex2 );
throw ex3;
} catch( Exception ex ) {
// ex => ex3
Exception baseEx = ex.GetBaseException(); // => ex1
}
accumulation sur la réponse de nawfal.
en utilisant sa réponse, il manquait une variable aggrEx, je l'ai ajoutée.
fichier ExceptionExtenstions.class:
// example usage:
// try{ ... } catch(Exception e) { MessageBox.Show(e.ToFormattedString()); }
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace YourNamespace
{
public static class ExceptionExtensions
{
public static IEnumerable<Exception> GetAllExceptions(this Exception exception)
{
yield return exception;
if (exception is AggregateException )
{
var aggrEx = exception as AggregateException;
foreach (Exception innerEx in aggrEx.InnerExceptions.SelectMany(e => e.GetAllExceptions()))
{
yield return innerEx;
}
}
else if (exception.InnerException != null)
{
foreach (Exception innerEx in exception.InnerException.GetAllExceptions())
{
yield return innerEx;
}
}
}
public static string ToFormattedString(this Exception exception)
{
IEnumerable<string> messages = exception
.GetAllExceptions()
.Where(e => !String.IsNullOrWhiteSpace(e.Message))
.Select(e => e.Message.Trim() + "\r\n" + e.StackTrace.Trim() );
string flattened = String.Join("\r\n\r\n", messages); // <-- the separator here
return flattened;
}
}
}