55 votes

.NET: Comment convertir Exception en chaîne?

Lorsqu'une exception est levée (pendant le débogage dans l'IDE), j'ai la possibilité d' afficher les détails de l'exception:

enter image description here

Mais dans le code si je l'appelle, exception.ToString() je n'ai pas à voir ces détails utiles:

System.Data.SqlClient.SqlException (0x80131904): Could not find stored procedure 'FetchActiveUsers'.
  [...snip stack trace...]

Mais Visual Studio a de la magie là où il peut l'exception de copie dans le presse-papiers:

enter image description here

Qui donne les détails utiles:

System.Data.SqlClient.SqlException was unhandled by user code
  Message=Could not find stored procedure 'FetchActiveUsers'.
  Source=.Net SqlClient Data Provider
  ErrorCode=-2146232060
  Class=16
  LineNumber=1
  Number=2812
  Procedure=""
  Server=vader
  State=62
  StackTrace:
       [...snip stack trace...]
  InnerException:

Eh bien, je veux que!

Quel serait le contenu de:

String ExceptionToString(Exception ex)
{ 
    //todo: Write useful routine
    return ex.ToString();
}

qui peut accomplir la même magie. Est-il un .NET fonction de quelque part? N' Exception ont une méthode secrète quelque part à la convertir en une chaîne de caractères?

57voto

Jason Points 125291

ErrorCode est spécifique à l' ExternalException, pas Exception et LineNumber et Number sont spécifiques à l' SqlException, pas Exception. Par conséquent, la seule manière d'obtenir ces propriétés à partir d'une extension générale de la méthode sur Exception est d'utiliser la réflexion pour itérer sur toutes les propriétés publiques.

De sorte que vous aurez à dire quelque chose comme:

public static string GetExceptionDetails(this Exception exception) {
    var properties = exception.GetType()
                            .GetProperties();
    var fields = properties
                     .Select(property => new { 
                         Name = property.Name,
                         Value = property.GetValue(exception, null)
                     })
                     .Select(x => String.Format(
                         "{0} = {1}",
                         x.Name,
                         x.Value != null ? x.Value.ToString() : String.Empty
                     ));
    return String.Join("\n", fields);
}

(Pas testé pour compliation des questions.)

.NET 2.0 compatible réponse:

public static string GetExceptionDetails(this Exception exception) 
{
    PropertyInfo[] properties = exception.GetType()
                            .GetProperties();
    List<string> fields = new List<string>();
    foreach(PropertyInfo property in properties) {
        object value = property.GetValue(exception, null);
        fields.Add(String.Format(
                         "{0} = {1}",
                         property.Name,
                         value != null ? value.ToString() : String.Empty
        ));    
    }         
    return String.Join("\n", fields.ToArray());
}

22voto

Gerben Rampaart Points 547

J'ai d'abord essayé la réponse de Jason (en haut), qui a plutôt bien fonctionné, mais je voulais aussi:

  • Faire une boucle itérative à travers les exceptions internes et les indenter.
  • Ignorer les propriétés null et augmente la lisibilité de la sortie.
  • Il inclut les métadonnées dans la propriété Data. (le cas échéant) mais exclut la propriété Data elle-même. (C'est inutile).

J'utilise maintenant ceci:

     public static void WriteExceptionDetails(Exception exception, StringBuilder builderToFill, int level)
    {
        var indent = new string(' ', level);

        if (level > 0)
        {
            builderToFill.AppendLine(indent + "=== INNER EXCEPTION ===");                
        }

        Action<string> append = (prop) =>
            {
                var propInfo = exception.GetType().GetProperty(prop);
                var val = propInfo.GetValue(exception);

                if (val != null)
                {
                    builderToFill.AppendFormat("{0}{1}: {2}{3}", indent, prop, val.ToString(), Environment.NewLine);
                }
            };

        append("Message");
        append("HResult");
        append("HelpLink");
        append("Source");
        append("StackTrace");
        append("TargetSite");

        foreach (DictionaryEntry de in exception.Data)
        {
            builderToFill.AppendFormat("{0} {1} = {2}{3}", indent, de.Key, de.Value, Environment.NewLine);
        }

        if (exception.InnerException != null)
        {
            WriteExceptionDetails(exception.InnerException, builderToFill, ++level);
        }
    }
 

Appelle comme ça:

         var builder = new StringBuilder();
        WriteExceptionDetails(exception, builder, 0);
        return builder.ToString();
 

6voto

Matt Points 6779

Il n'existe pas de méthode secrète. Vous pourriez probablement juste de remplacer l' ToString() méthode et de construire la chaîne que vous souhaitez.

Des choses comme le code d'erreur et le Message sont seulement des propriétés de l'exception que vous pouvez ajouter à la chaîne souhaitée de sortie.


Mise à jour: Après re-lecture de votre question et de penser plus à ce sujet, Jason réponse est plus probablement que vous êtes désireux. En substituant l' ToString() méthode ne serait utile pour les exceptions que vous avez créé, pas ceux déjà mis en œuvre. Il ne fait pas de sens à la sous classe des exceptions existantes juste pour ajouter cette fonctionnalité.

4voto

Pour afficher certains détails à l’utilisateur, vous devez utiliser ex.Message . Pour afficher aux développeurs, vous aurez probablement besoin de ex.Message et ex.StackTrace .

Il n'y a pas de méthode 'secrète', vous pouvez considérer que la propriété Message convient le mieux pour un message convivial.

Veillez également à ce que, dans certains cas, vous ayez une exception interne, à l'exception que vous attrapiez, ce qui serait également utile pour la journalisation.

2voto

Youngjae Points 1457

Chaque de gauche le nom de la propriété dans l'Exception. Si vous souhaitez afficher de Message de domaine, vous pouvez le faire

return ex.Message;

Assez simple. De même, le suivi de pile peut être affiché en tant que lien ci-dessous.

Un exemple complet de StackTrace: http://msdn.microsoft.com/en-us/library/system.exception.stacktrace.aspx

et à l'Exception de la classe: http://msdn.microsoft.com/en-us/library/system.exception.aspx

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