Ответ 1
Ты вдохновил меня на то, чтобы тыкать с этим - спасибо, что не спал всю ночь.:) Здесь один из способов сделать это.
У Visual Studio действительно отличная поддержка точек останова. Одна из более крутых функций заключается в том, что вы можете сказать, что он запускает макрос Visual Studio при ударе точки останова. Эти макросы имеют полный доступ к среде разработки, то есть они могут делать все, что вы могли бы сделать вручную на клавиатуре, включая установку других точек останова.
Это решение состоит в том, чтобы: 1) установить в вашей программе попытку/улов верхнего уровня в вашей программе, чтобы поймать все исключения, 2) поставить точку останова в блоке catch, которая запускает ваш макрос, и 3) заставить макрос смотреть на исключение выяснить, откуда она взялась, и поставить там точку останова. Когда вы запускаете его в отладчике и возникает исключение, у вас будет новая точка останова в строке нарушения кода.
Возьмите эту программу:
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!");
}
}
}
Цель состоит в том, чтобы программно установить точку останова на throw
в func3, когда вы запустили ее в отладчике и получили ошибку. Для этого сначала создайте новый макрос Visual Studio (я назвал my SetBreakpointOnException). Вставьте это в новый модуль MyDebuggerMacros или что-то еще:
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
Как только этот макрос будет установлен, вернитесь в блок catch
и установите точку останова с F9. Затем щелкните правой кнопкой мыши по кругу красных точек и выберите "When Hit...". В нижней части появившегося диалогового окна есть возможность указать, чтобы он выполнял макрос - выпадал из списка и выбирал ваш макрос. Теперь вы должны получить новые контрольные точки, когда ваше приложение выдает необработанные исключения.
Заметки и оговорки об этом:
- Я не гуру регулярных выражений, я уверен, что кто-то еще может взломать что-то лучше.
- Это не обрабатывает вложенные исключения (свойство InnerException) - вы можете побить голову против этого, если хотите.:) Проверьте GetExpression ( "e.InnerException" ) и, возможно, рекурсия.
- Он выполняет синтаксический анализ текста на строке StackTrace expetion, а не на более сложном анализе графа объектов (выкапывании в Exception.TargetSite и использовании отражения). Обычные оговорки касаются хрупкости этого подхода.
- По какой-то причине кажется, что точка останова находится в каком-то "альтернативном пространстве". Как только начальный сеанс отладки завершится, вы не увидите новую точку останова в своем коде. Но это там, если вы снова запустите программу в отладчике, и такие вещи, как "Disable All Breakpoints", влияют на нее. Было бы неплохо узнать о том, что происходит, если кто-то хочет найти способ очистить это. Может быть, копаться в файле .suo?
Надеюсь, это поможет!