39 votes

Dans une exception .net, comment obtenir un stacktrace avec des valeurs d'argument

Je suis en train d'ajouter un gestionnaire d'exceptions non gérées dans .net (c#) qui devrait être utile pour l'utilisateur que possible. Les utilisateurs finaux sont surtout des programmeurs, donc ils ont juste besoin d'un indicateur de ce que l'objet sont-ils manipuler mal.

Je suis l'élaboration d'un windows similaire à la windows XP de rapport d'erreur lorsqu'une application se bloque, mais qui donne autant de imediate d'informations que possible imediatly à propos de l'exception levée.

Alors que la trace de la pile permet moi (depuis que j'ai le code source) pour localiser la source du problème, les utilisateurs n'ont pas, et c'est ainsi qu'ils sont perdus sans plus d'informations. Inutile de dire que j'ai passer beaucoup de temps à l'appui de l'outil.

Il y a un peu d'exceptions comme KeyNotFoundException jeté par la collection Dictionnaire qui vraiment me gonfler, car ils ne pas inclure dans le message la clé qui n'a pas été trouvé. Je peux remplir mon code avec des tonnes de blocs try catch mais plutôt agressive et est beaucoup plus de code à maintenir, pour ne pas mentionner une tonne plus de chaînes qui ont fini par être localisé.

Enfin, la question: Est-il possible de l'obtenir (à l'exécution) les valeurs des arguments de chaque fonction dans la trace de pile d'appel? Qui seul pouvait résoudre 90% des appels de soutien.

7voto

user7375 Points 569

Je ne pense pas que System.Diagnostics.StackFrame fournisse des informations d'argument (autres que la signature de la méthode).

Vous pouvez instrumenter les appels problématiques avec la journalisation du suivi via AOP, ou même utiliser ses fonctions d'interception des exceptions pour journaliser de manière conditionnelle sans avoir à jeter de code. Jetez un coup d'œil sur http://www.postsharp.org/ .

6voto

Steve Morgan Points 9296

De même, je n'ai pas trouvé quoi que ce soit pour dériver les paramètres automatiquement au moment de l'exécution. Au lieu de cela, j'ai utilisé un Visual Studio add-in pour générer du code qui explicitement les paquets les paramètres, comme ceci:

public class ExceptionHandler
{
    public static bool HandleException(Exception ex, IList<Param> parameters)
    {
        /*
         * Log the exception
         * 
         * Return true to rethrow the original exception,
         * else false
         */
    }
}

public class Param
{
    public string Name { get; set; }
    public object Value { get; set; }
}

public class MyClass
{
    public void RenderSomeText(int lineNumber, string text, RenderingContext context)
    {
        try
        {
            /*
             * Do some work
             */
            throw new ApplicationException("Something bad happened");
        }
        catch (Exception ex)
        {
            if (ExceptionHandler.HandleException(
                    ex, 
                    new List<Param>
                    {
                        new Param { Name = "lineNumber", Value=lineNumber },
                        new Param { Name = "text", Value=text },
                        new Param { Name = "context", Value=context}
                    }))
            {
                throw;
            }
        }
    }
}

EDIT: ou sinon, en faisant le paramètre à HandleException un tableau params:

public static bool HandleException(Exception ex, params Param[] parameters)
{
   ...
}

...
if (ExceptionHandler.HandleException(
                    ex, 
                    new Param { Name = "lineNumber", Value=lineNumber },
                    new Param { Name = "text", Value=text },
                    new Param { Name = "context", Value=context}
                    ))
{
    throw;
}
...

C'est un peu une douleur en générant le code supplémentaire pour transmettre explicitement les paramètres du gestionnaire d'exception, mais avec l'utilisation d'un add-in vous pouvez au moins l'automatiser.

Un attribut personnalisé peut être utilisé pour annoter tous les paramètres que vous ne voulez pas le complément à transmettre au gestionnaire d'exception:

public UserToken RegisterUser( string userId, [NoLog] string password )
{
}

2ÈME EDIT:

Rappelez-vous, j'avais complètement oublié AVICode:

http://www.avicode.com/

Ils utilisent interception d'appels techniques pour fournir exactement ce genre d'information, il doit donc être possible.

4voto

Wolfwyrd Points 7142

Malheureusement, vous ne pouvez pas obtenir les valeurs réelles des paramètres de la pile des appels, sauf avec les outils de débogage réellement attaché à l'application. Cependant, en utilisant la StackTrace et structure de pile d'objets dans le Système.Diagnostics, vous pouvez marcher dans la pile des appels et de lire toutes les méthodes invoquées et les noms des paramètres et types. Vous voulez faire cela comme:

System.Diagnostics.StackTrace callStack = new System.Diagnostics.StackTrace();
System.Diagnostics.StackFrame frame = null;
System.Reflection.MethodBase calledMethod = null;
System.Reflection.ParameterInfo [] passedParams = null;
for (int x = 0; x < callStack.FrameCount; x++)
{
    frame = callStack.GetFrame(x);
    calledMethod = frame.GetMethod();
    passedParams = calledMethod.GetParameters();
    foreach (System.Reflection.ParameterInfo param in passedParams)
        System.Console.WriteLine(param.ToString()); 
}

Si vous avez besoin de valeurs réelles, alors vous allez avoir besoin de prendre les minidumps et de les analyser, j'en ai peur. Informations sur l'obtention des informations de vidage peut être trouvé à:

http://www.debuginfo.com/tools/clrdump.html

2voto

SchlaWiener Points 9682

Il est un outil logiciel de redgate là-bas, qui a l'air très prometteuse.

http://www.red-gate.com/products/dotnet-development/smartassembly/

Actuellement nous sommes à la perception de nos clients des rapports d'erreur par e-mail et j'ai parfois du mal avec certains important de données manquantes (pour la plupart quelques très variables de base, comme l'id de l'enregistrement en cours afin que je puisse reproduire le bug). Je havn'pas testé cet outil, mais à partir de ma compréhension, il fait quoi recueille les valeurs de l'argument et des variables locales dans la pile.

1voto

Peter Meyer Points 11163

Je ne crois pas qu'il existe un mécanisme intégré. La récupération de chaque image de la trace de la pile, tout en vous permettant de déterminer la méthode dans la trace, ne vous donne que les informations de type reflétées sur cette méthode. Aucune information de paramètre. Je pense que c’est pourquoi certaines exceptions, notamment ArgumentException, et. Al. fournissez un mécanisme pour spécifier la valeur de l'argument impliqué dans l'exception, car il n'existe pas de moyen facile de l'obtenir.

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