Vous m'avez inspiré pour fouiner autour de cela - merci de m'avoir éveillé toute la nuit. :) Voici une façon de le faire.
Visual Studio offre un très bon support de points d'arrêt. L'une des fonctionnalités les plus intéressantes est que vous pouvez lui indiquer d'exécuter une macro Visual Studio lorsque le point d'arrêt est atteint. Ces macros ont un accès complet à l'environnement de développement, c'est-à-dire qu'elles peuvent faire tout ce que vous pouvez faire manuellement au clavier, y compris la définition d'autres points d'arrêt. Cette solution consiste à: 1) placer un try/catch de niveau supérieur dans votre programme pour intercepter toutes les exceptions, 2) placer un point d'arrêt dans le bloc catch qui exécute votre macro et 3) faire en sorte que la macro regarde l'exception pour comprendre d'où il vient, et mettre un point d'arrêt là. Lorsque vous l'exécutez dans le débogueur et qu'une exception se produit, vous avez un nouveau point d'arrêt sur la ligne de code incriminée.
Prenez cet exemple de programme:
using System;
namespace ExceptionCallstack
{
class Program
{
static void Main(string[] args)
{
try
{
func1();
}
catch (Exception e)
{
Console.WriteLine("Oops");
Console.ReadKey();
}
}
static void func1()
{
func2();
}
static void func2()
{
func3();
}
static void func3()
{
throw new Exception("Boom!");
}
}
}
L'objectif est de définir un programme sur ce point d'arrêt dans throw
fonc3 lorsque vous l'exécutez dans le débogueur et obtenez l'erreur. Pour ce faire, créez d'abord une nouvelle macro Visual Studio (j'ai appelé la mienne SetBreakpointOnException). Coller dans un nouveau module MyDebuggerMacros ou autre:
Imports System
Imports EnvDTE
Imports EnvDTE80
Imports EnvDTE90
Imports System.Diagnostics
Imports System.Text.RegularExpressions
Public Module DebuggerMacros
Sub SetBreakpointOnException()
Dim output As String = ""
Dim stackTrace As String = DTE.Debugger.GetExpression("e.StackTrace").Value
stackTrace = stackTrace.Trim(New Char() {""""c})
Dim stackFrames As String() = Regex.Split(stackTrace, "\\r\\n")
Dim r As New Regex("^\s+at .* in (?<file>.+):line (?<line>\d+)$", RegexOptions.Multiline)
Dim match As Match = r.Match(stackFrames(0))
Dim file As String = match.Groups("file").Value
Dim line As Integer = Integer.Parse(match.Groups("line").Value)
DTE.Debugger.Breakpoints.Add("", file, line)
End Sub
End Module
Une fois cette macro est en place, revenir au bloc catch
et mettre un point d'arrêt avec F9. Cliquez ensuite avec le bouton droit sur le cercle de point d'arrêt rouge et sélectionnez "When Hit ...". Au bas de la boîte de dialogue résultante, il y a une option pour lui dire d'exécuter une macro: faites défiler la liste et choisissez votre macro. Vous devriez maintenant obtenir de nouveaux points d'arrêt lorsque votre application renverra des exceptions non gérées.
Notes et mises en garde à ce sujet:
- Je suis pas un gourou regex, je suis sûr que quelqu'un d'autre peut concocter quelque chose de mieux.
- Cela ne gère pas les exceptions imbriquées (propriété InnerException) - vous pouvez vous battre contre cela si vous le souhaitez. :) Vérifiez GetExpression ("e.InnerException") et recurse, peut-être.
- Il effectue l'analyse de texte sur la chaîne StackTrace de l'excpetion, pas d'analyse de graphe d'objet plus sophistiquée (en explorant Exception.TargetSite et en utilisant la réflexion). Les mises en garde habituelles s'appliquent à la fragilité de cette approche.
- Pour une raison quelconque, il semble mettre le point d'arrêt dans un "espace alternatif". Une fois la session de débogage initiale terminée, vous ne voyez pas le nouveau point d'arrêt dans votre code. Mais il est là si vous exécutez le programme à nouveau dans le débogueur, et des choses comme "Désactiver tous les points d'arrêt" l'affectent. Ce serait bien d'apprendre ce qui se passe, si quelqu'un a envie de trouver un moyen de nettoyer cela. Peut-être creuser dans le fichier .suo?
Espérons que cela aide!
Il doit être, je le fais en C++ tout le temps via 'if (IsDebuggerPresent()) DebugBreak();', je l'ai dans le constructeur de plusieurs de mes classes d'exception. –