Программно применять / деактивировать точки останова в Visual Studio - PullRequest
16 голосов
/ 09 мая 2009

Независимо от других опций, которые могут достичь того же результата (то есть добавление точек останова) вручную), можно ли программно добавить точку останова в исходный код проекта Visual Studio?

Например:

try
{
    FunctionThatThrowsErrors(obj InscrutableParameters);
}
catch(Exception ex)
{
    Log.LogTheError(ex);
    AddBreakPointToCallingFunction();
}

Таким образом, при следующем запуске в режиме отладки он автоматически установит точки останова во всех точках, которые вызвали проблемы во время последнего запуска.

Я не говорю, что это особенно полезный способ отладки. Мне просто интересно, есть ли возможность.

Ответы [ 5 ]

45 голосов
/ 09 мая 2009

Вы можете просто позвонить System.Diagnostics.Debugger.Break().

Вы также можете сказать Visual Studio, что нужно разбить все исключения, даже обработанные, перейдя в меню к Debug->Exceptions... и отметив Thrown везде, где в данный момент проверяется только «Необработанный пользователь».

39 голосов
/ 09 мая 2009

Вы вдохновили меня возиться с этим - спасибо, что не давали мне спать всю ночь. :) Вот один из способов сделать это.

Visual Studio имеет отличную поддержку точек останова. Одна из особенностей кулера заключается в том, что вы можете указать ему запускать макрос Visual Studio при достижении точки останова. Эти макросы имеют полный доступ к среде разработки, т. Е. Они могут делать все, что вы можете делать вручную на клавиатуре, включая установку других точек останова.

Это решение состоит в том, чтобы: 1) поместить в вашу программу команду try / catch верхнего уровня для перехвата всех исключений, 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 (я назвал мой 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. Затем щелкните правой кнопкой мыши на красном круге точки останова и выберите «При попадании ...». В нижней части появившегося диалогового окна есть опция, позволяющая ему запустить макрос - выпадающий список и выберите свой макрос. Теперь вы должны получать новые точки останова, когда ваше приложение генерирует необработанные исключения.

Примечания и предостережения об этом:

  • Я не Гуру регулярных выражений, я уверен, что кто-то другой может сделать что-то лучше.
  • Это не обрабатывает вложенные исключения (свойство InnerException) - вы можете разбить голову против этого, если хотите. :) Проверьте для GetExpression ("e.InnerException") и рекурсивно, возможно.
  • Он выполняет синтаксический анализ текста в строке StackTrace исключения, а не более сложный анализ графа объекта (копание в Exception.TargetSite и использование отражения). Обычные предостережения касаются хрупкости этого подхода.
  • Почему-то кажется, что точка останова помещается в какое-то "альтернативное пространство". Когда начальный сеанс отладки закончен, вы не видите новую точку останова в своем коде. Но он есть, если вы снова запустите программу в отладчике, и такие вещи, как «Отключить все точки останова», влияют на это. Было бы неплохо узнать о том, что происходит, если кто-то захочет найти способ это исправить. Может, копаться в файле .suo?

Надеюсь, это поможет!

4 голосов
/ 09 мая 2009

Это на самом деле не отвечает на ваш вопрос, но вы можете отключить отладчик в зависимости от условий, которые вы установили с помощью Debug.Assert . Таким образом, вместо того, чтобы сказать «в следующий раз, когда я запустил функцию, которая вызвала исключение, сломайте», вы можете добавить в свою функцию утверждения, чтобы они нарушались, когда условия не соответствуют требованиям. В конце концов, нет никакой гарантии, что функция на этот раз сгенерирует исключение только потому, что она сгенерировала исключение в прошлый раз. :)

2 голосов
/ 09 мая 2009

Я не думаю, что вы действительно можете «добавить точку останова», но вы можете указать отладчику приостановить выполнение, чтобы вы могли проверить, что пошло не так, вызвав System.Diagnostics.Debugger.Break ()

0 голосов
/ 25 мая 2010

Кроме того, в Visual Basic есть ключевое слово Stop, которое по существу будет действовать как точка останова и прерывание выполнения.

...