Прерываться всякий раз, когда вводится файл (или класс)

В Visual Studio есть ли способ отключить отладчик при вводе определенного файла (или класса)? Пожалуйста, не отвечайте «просто установите точку останова в начале каждого метода» :)

Я использую C#.

Указание языка, с которым вы работаете (Visual Studio может быть C#, C++, Managed C++ или VB.Net), может помочь людям дать вам лучшие предложения.

Onorio Catenacci 30.10.2008 18:40

Какой ответ вы придумали?

ScottCher 03.11.2008 17:38

Просто установите точку останова в начале каждого метода.

mxcl 12.02.2009 04:12

Эта функция недоступна из коробки в Visual Studio. Для этого вам нужно пометить каждый метод или вставить Debugger.Break (). (см. мой комментарий, как это сделать с помощью макроса, если вы используете C / C++) В качестве общего принципа вы можете считать, что «тестирование - это круто, отладка - отстой».

devdimi 12.02.2009 05:02

Почему ты хочешь сделать это? Возможно, мы сможем вам помочь с этой информацией :)

guerda 12.02.2009 12:27

Я не уверен, что ваше добавление C# было ответом на мой макрос, но макросы нельзя писать на C#. Очевидно, они все еще могут взаимодействовать с проектом C#.

Richard Szalay 17.02.2009 01:38
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
19
6
4 489
23
Перейти к ответу Данный вопрос помечен как решенный

Ответы 23

Нет. Вернее, да, но это предполагает установку точки останова в начале каждого метода.

Не то, чтобы я в курсе. Лучшее, что вы можете сделать, - это поставить точку останова в каждом методе файла или класса. Что ты пытаешься сделать? Вы пытаетесь выяснить, какой метод заставляет что-то измениться? Если это так, возможно, точка останова по данным будет более подходящей.

System.Diagnostics.Debugger.Break();

(в начале каждого метода)

Что ж, как все говорят, это включает установку точки останова в начале каждого метода. Но вы не видите более широкой картины.

Чтобы это вообще работало, в начале каждого метода должна быть установлена ​​точка останова. Независимо от того, делаете ли вы это вручную или отладчик делает это автоматически, эти точки останова должны быть установлены, чтобы это работало.

Таким образом, действительно возникает вопрос: «Если в этой функциональности достаточно необходимости, стоит ли встроить в отладчик автоматические средства установки всех этих точек останова?». И ответ: «Не совсем».

На самом деле, я мог видеть полезность чего-то подобного для выполнения быстрой и грязной проверки покрытия кода. Я сам иногда делал что-то подобное для новых функций, которые я пишу, где я ставлю точку останова в каждой точке принятия решения, чтобы убедиться, что модульные тесты имеют хорошее покрытие.

Michael Burr 30.10.2008 18:51

@Mike B: Вот почему Господь (или, по крайней мере, BillG) дал нам connect.microsoft.com для кампании за новые функции.

James Curran 30.10.2008 18:54

Я вижу несколько веских причин для этого, и подход АОП или postsharp.org - хороший способ реализации.

MrTelly 12.02.2009 11:52

На самом деле я вижу много ситуаций, когда это было бы удобно, загружен ли ваш класс, когда что-то, что вы написали, вызывается и как и почему из внешнего кода. Я думаю, что на самом деле это было бы проще, чем устанавливать точку останова в каждом методе, просто поставить паузу в пространстве памяти классов, не так ли?

Henry B 12.02.2009 12:29

Кроме того, что, если он хочет сломаться всякий раз, когда осуществляется доступ к члену класса / объекта?

Henry B 12.02.2009 12:30

@PintSizedCat: к сожалению, C# еще не поддерживает точки останова по данным, если вы это имеете в виду

Steve Eisner 13.02.2009 14:19

Я не уверен, о чем вы? "Не делай этого?" Отладчик VC++ и WinDebug могут это сделать. В этих случаях ответ был не «не совсем». Может я что то упускаю?

Aardvark 18.02.2009 18:24

МОЖЕТ ли отладчик VC++ сделать это (автоматически устанавливать точку останова для каждой записи функции)? Сначала я об этом слышу ....

James Curran 18.02.2009 18:58

Минус 1. Вы не отвечаете на вопрос. Если не знаешь, не отвечаешь.

Eric Ouellet 22.06.2018 21:45

Вы можете написать метод-оболочку, с помощью которого вы будете делать КАЖДЫЙ вызов в своем приложении. Затем вы устанавливаете точку останова в этом единственном методе. Но ... ты был бы сумасшедшим, если бы сделал такую ​​вещь.

Вы можете начать с введения некоторого вида аспектно-ориентированного программирования - см., Например, это объяснение - а затем поставить точку останова в единственном методе OnEnter.

В зависимости от того, какой фреймворк AOP вы выберете, он потребует небольшого украшения в вашем коде и внесет небольшие накладные расходы (которые вы можете удалить позже), но, по крайней мере, вам не нужно везде устанавливать точки останова. В некоторых фреймворках вы могли бы даже ввести его без изменения кода, просто с помощью XML-файла на стороне?

Вы можете установить для этого точку останова памяти и установить на чтение. Я думаю, что вы должны читать большую часть времени, когда вызываете функцию-член. Я не уверен в статических функциях.

you can use the following macro:

#ifdef _DEBUG
#define DEBUG_METHOD(x) x DebugBreak();
#else
#define DEBUG_METHOD(x) x
#endif

#include <windows.h>

DEBUG_METHOD(int func(int arg) {)
    return 0;
}

при вводе функции он сломается в отладчике

ЕСЛИ это C++, о котором вы говорите, то вам, вероятно, сойдет с рук (чертовски много работы), установив точку останова в коде преамбулы в CRT или написав код, который изменяет код преамбулы, чтобы придерживаться INT 3 там только для функций, сгенерированных из рассматриваемого класса ... Это, кстати, МОЖЕТ быть сделано во время выполнения ... Вам нужно, чтобы созданный PE-файл изменил себя, возможно, перед перемещением, чтобы вставить все перерывы в там...

Моим единственным другим предложением было бы написать макрос, который использует предопределенный макрос __FUNCTION__, в котором вы будете искать любую функцию, являющуюся частью рассматриваемого класса, и, если необходимо, вставить

__asm { int 3 }

в вашем макросе, чтобы VS сломался ... Это избавит вас от необходимости устанавливать точки останова в начале каждой функции, но вам все равно придется придерживаться вызова макроса, что намного лучше, если вы спросите меня. Думаю, я где-то читал о том, как можно определить или переопределить код преамбулы, вызываемый для каждой функции ... Я посмотрю, что смогу найти.

Я бы подумал, что подобный хак можно использовать для определения того, какой ФАЙЛ вы вводите, но вам ВСЕГДА нужно размещать ВАШ функциональный макрос по всему вашему коду, иначе он никогда не будет вызван, и, ну, это в значительной степени то, что вы не хотели сделать.

Вы можете написать макрос Visual Studio, который получит список всех методов класса (скажем, путем чтения файла .map, созданного вместе с исполняемым файлом, и поиска в нем правильных имен символов (а затем удаления этих имен)), а затем использовать Breakpoints.add() для программного добавления точек останова к этим функциям.

Это отлично работает в WinDbg:

bm exename!CSomeClass::*

(Чтобы прояснить, приведенная выше строка устанавливает точку останова для всех функций в классе, как и OP запрашивает, не прибегая к взлому CRT или глупости макросов)

Если вы хотите использовать макрос, тогда принятый ответ от этот вопрос

Должен быть тривиально преобразован в ваши нужды, заставив функцию поиска искать методы, свойства и конструкторы (по желанию), также, вполне возможно, есть способ получить ту же информацию из идентификаторов / символов, которые будут более стабильными (хотя, возможно, немного сложнее).

Используйте Отладчик.Break (); (из пространства имен System.Diagnostics)

Поместите его вверху каждой функции, которую вы хотите "сломать".

void MyFunction()
{
    Debugger.Break();
    Console.WriteLine("More stuff...");
}

Разве не самый простой способ приблизиться к этому - просто установить точку останова в конструкторе (при условии, что у вас есть только один - или каждый из них в случае нескольких конструкторов)?

Это нарушит отладку при первом создании экземпляра класса в случае нестатического конструктора, а в случае статического конструктора / класса вы перейдете к отладке, как только Visual Studio решит инициализировать ваш класс.

Это определенно избавляет вас от необходимости устанавливать точку останова в методе каждый внутри класса.

Конечно, вы не будете продолжать прерывать отладку при последующем повторном входе в код класса (при условии, что вы используете тот же экземпляр объекта в следующий раз), однако, если вы повторно создаете экземпляр нового объекта каждый раз из в вызывающем коде вы можете смоделировать это.

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

Предполагая, что вас интересуют только общедоступные методы, т.е. когда методы класса вызываются «извне», я еще раз подключу дизайн по контракту.

Вы можете привыкнуть писать свои общедоступные функции следующим образом:

public int Whatever(int blah, bool duh)
{
    // INVARIANT (i)
    // PRECONDITION CHECK (ii)

    // BODY (iii)

    // POSTCONDITION CHECK (iv)
    // INVARIANT (v)

}

Затем вы можете использовать функцию Invariant (), которую вы вызовете в (i) и установить в нем точку останова. Затем проверьте стек вызовов, чтобы узнать, откуда вы пришли. Конечно, вы тоже назовете это в (v); если вас действительно интересуют только точки входа, вы можете использовать вспомогательную функцию для вызова Invariant из (i) и еще одну из (v).

Конечно, это лишний код, но

  1. В любом случае это полезный код, а структура является шаблонной, если вы используете дизайн по контракту.
  2. Иногда вы хотите, чтобы точки останова исследовали некорректное поведение, например, недопустимое состояние объекта, в этом случае инварианты могут оказаться бесценными.

Для объекта, который всегда действителен, функция Invariant () просто имеет тело, которое возвращает true. Вы все еще можете поставить там точку останова.

Это просто идея, по общему признанию, у нее есть след, поэтому просто рассмотрите ее и используйте, если она вам нравится.

Можно использовать Debugger.Launch() и Debugger.Break() в сборке System.Diagnostics

Ответ принят как подходящий

Макросы могут быть вашим другом. Вот макрос, который добавит точку останова к каждому методу в текущем классе (поместите курсор где-нибудь в классе перед его запуском).

Public Module ClassBreak
    Public Sub BreakOnAnyMember()
        Dim debugger As EnvDTE.Debugger = DTE.Debugger
        Dim sel As EnvDTE.TextSelection = DTE.ActiveDocument.Selection
        Dim editPoint As EnvDTE.EditPoint = sel.ActivePoint.CreateEditPoint()
        Dim classElem As EnvDTE.CodeElement = editPoint.CodeElement(vsCMElement.vsCMElementClass)

        If Not classElem Is Nothing Then
            For Each member As EnvDTE.CodeElement In classElem.Children
                If member.Kind = vsCMElement.vsCMElementFunction Then
                    debugger.Breakpoints.Add(member.FullName)
                End If
            Next
        End If
    End Sub

End Module

Редактировать: Обновлено, чтобы добавить точку останова по имени функции, а не по номеру файла / строки. Это «чувствуется» лучше, и его будет легче распознать в окне точек останова.

Не могли бы вы дать краткую ссылку на то, как создавать макросы в Studio?

JoelFan 15.02.2009 19:12

Получите доступ к макросам через Tools-> Macros-> Macros IDE, затем создайте модуль с именем ClassBreak и вставьте приведенный выше код. Затем вы можете получить доступ к макросу через Tools-> Macros-> Macro Explorer (просто дважды щелкните ClassBreak -> BreakOnAnyMember, чтобы запустить его)

Richard Szalay 16.02.2009 09:53

+1. добавьте, пожалуйста, макросы для удаления всех этих точек останова после.

Avram 16.02.2009 16:36

Самое простое решение - выбрать все точки останова для этого файла в «Отладка»> «Windows»> «Точки останова» (или CTRL-D, B) и нажать «Удалить» (X). Если в этом окне не отображаются точки останова, выберите Столбцы> Имя

Richard Szalay 16.02.2009 17:02

Если это полезно, в VS08 ввод Ctrl + Shift + F9 удалит все точки останова.

Adam A 21.01.2010 00:08

Работал для 2/3 прогонов, а затем завершился неудачно с исключением «как разрешить неопределенную ошибку (исключение из H_RESULT 0x80004005: EFAIL)» в VS2010

user1502952 05.09.2012 14:55

@ user1502952 - Единственное, что я могу себе представить, это положение курсора вне класса (или что-то непонятное) или столкновение точек останова.

Richard Szalay 05.09.2012 15:45

Возможно, вы могли бы использовать структуру АОП, такую ​​как PostSharp, чтобы взламывать отладчик всякий раз, когда вводится метод. Взгляните на очень короткое руководство по эта страница для примера, как вы можете регистрировать / отслеживать всякий раз, когда вводится метод.

Вместо ведения журнала в вашем случае вы можете поместить оператор Debugger.Break () в обработчик OnEntry. Хотя отладчик остановился бы не на ваших методах, а в обработчике OnEntry (поэтому я не уверен, действительно ли это помогает).

Вот очень простой пример:

Класс аспекта определяет обработчик OnEntry, который вызывает Debugger.Break ():

[Serializable]
public sealed class DebugBreakAttribute : PostSharp.Laos.OnMethodBoundaryAspect
{
    public DebugBreakAttribute() {}
    public DebugBreakAttribute(string category) {}
    public string Category { get { return "DebugBreak"; } }

    public override void OnEntry(PostSharp.Laos.MethodExecutionEventArgs eventArgs)
    {
        base.OnEntry(eventArgs);
        // debugger will break here. Press F10 to continue to the "real" method
        System.Diagnostics.Debugger.Break();
    }
}

Затем я могу применить этот аспект к своему классу, где я хочу, чтобы отладчик прерывал работу всякий раз, когда вызывается метод:

[DebugBreak("DebugBreak")]
public class MyClass
{
    public MyClass()
    {
        // ...
    }
    public void Test()
    {
        // ...
    }
}

Теперь, если я создам и запустил приложение, отладчик будет останавливаться в обработчике OnEntry () всякий раз, когда вызывается один из методов MyClass. Все, что мне нужно сделать, это нажать F10, и я использую метод MyClass.

Безумный метод с использованием отражения. Подробнее см. Документацию для MethodRental.SwapMethodBody. В псевдокоде:

void SetBreakpointsForAllMethodsAndConstructorsInClass (string classname)
{
  find type information for class classname
  for each constructor and method
    get MSIL bytes
    prepend call to System.Diagnostics.Debugger.Break to MSIL bytes
    fix up MSIL code (I'm not familiar with the MSIL spec. Generally, absolute jump targets need fixing up)
    call SwapMethodBody with new MSIL
}

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

Файлы не существуют во время выполнения (учтите, что частичные классы ничем не отличаются - с точки зрения кода - от помещения всего в один файл). Поэтому требуется макро-подход (или код в каждом методе).

Сделать то же самое с типом (который существует во время выполнения) может быть возможным, но, вероятно, будет очень навязчивым, создавая больший потенциал для heisenbugs. «Самый простой» путь к этому, вероятно, будет заключаться в использовании прокси-инфраструктуры удаленного взаимодействия .NET (пример использования прозрачного прокси-сервера см. В реализации MOQ).

Сводка: используйте макрос или выберите все, а затем установите точку останова (ctrl-A, F9).

Эта функция реализована в VS для нативного C++. crtl-B и укажите "функцию" как "Classname :: *", это устанавливает точку останова в начале каждого метода в классе. Наборы точек останова сгруппированы вместе в окне точек останова (ctrl-alt-B), поэтому их можно включать, отключать и удалять как группу.

К сожалению, макрос - лучший вариант для управляемого кода.

Решение C++, описанное здесь: blogs.msdn.com/habibh/archive/2009/09/10/…

Marek 05.03.2010 12:13

Джоэл, похоже, ответ будет «нет». Невозможно без точки останова для каждого метода.

Чтобы удалить точки останова, установленные принятым ответом, добавьте еще один макрос со следующим кодом

Public Sub RemoveBreakOnAnyMember()
    Dim debugger As EnvDTE.Debugger = DTE.Debugger

    Dim bps As Breakpoints
    bps = debugger.Breakpoints

    If (bps.Count > 0) Then
        Dim bp As Breakpoint
        For Each bp In bps
            Dim split As String() = bp.File.Split(New [Char]() {"\"c})

            If (split.Length > 0) Then
                Dim strName = split(split.Length - 1)
                If (strName.Equals(DTE.ActiveDocument.Name)) Then
                    bp.Delete()
                End If
            End If
        Next
    End If
End Sub

Другие вопросы по теме