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





Нет. Вернее, да, но это предполагает установку точки останова в начале каждого метода.
Не то, чтобы я в курсе. Лучшее, что вы можете сделать, - это поставить точку останова в каждом методе файла или класса. Что ты пытаешься сделать? Вы пытаетесь выяснить, какой метод заставляет что-то измениться? Если это так, возможно, точка останова по данным будет более подходящей.
System.Diagnostics.Debugger.Break();
(в начале каждого метода)
Что ж, как все говорят, это включает установку точки останова в начале каждого метода. Но вы не видите более широкой картины.
Чтобы это вообще работало, в начале каждого метода должна быть установлена точка останова. Независимо от того, делаете ли вы это вручную или отладчик делает это автоматически, эти точки останова должны быть установлены, чтобы это работало.
Таким образом, действительно возникает вопрос: «Если в этой функциональности достаточно необходимости, стоит ли встроить в отладчик автоматические средства установки всех этих точек останова?». И ответ: «Не совсем».
На самом деле, я мог видеть полезность чего-то подобного для выполнения быстрой и грязной проверки покрытия кода. Я сам иногда делал что-то подобное для новых функций, которые я пишу, где я ставлю точку останова в каждой точке принятия решения, чтобы убедиться, что модульные тесты имеют хорошее покрытие.
@Mike B: Вот почему Господь (или, по крайней мере, BillG) дал нам connect.microsoft.com для кампании за новые функции.
Я вижу несколько веских причин для этого, и подход АОП или postsharp.org - хороший способ реализации.
На самом деле я вижу много ситуаций, когда это было бы удобно, загружен ли ваш класс, когда что-то, что вы написали, вызывается и как и почему из внешнего кода. Я думаю, что на самом деле это было бы проще, чем устанавливать точку останова в каждом методе, просто поставить паузу в пространстве памяти классов, не так ли?
Кроме того, что, если он хочет сломаться всякий раз, когда осуществляется доступ к члену класса / объекта?
@PintSizedCat: к сожалению, C# еще не поддерживает точки останова по данным, если вы это имеете в виду
Я не уверен, о чем вы? "Не делай этого?" Отладчик VC++ и WinDebug могут это сделать. В этих случаях ответ был не «не совсем». Может я что то упускаю?
МОЖЕТ ли отладчик VC++ сделать это (автоматически устанавливать точку останова для каждой записи функции)? Сначала я об этом слышу ....
Минус 1. Вы не отвечаете на вопрос. Если не знаешь, не отвечаешь.
Вы можете написать метод-оболочку, с помощью которого вы будете делать КАЖДЫЙ вызов в своем приложении. Затем вы устанавливаете точку останова в этом единственном методе. Но ... ты был бы сумасшедшим, если бы сделал такую вещь.
Вы можете начать с введения некоторого вида аспектно-ориентированного программирования - см., Например, это объяснение - а затем поставить точку останова в единственном методе 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).
Конечно, это лишний код, но
Для объекта, который всегда действителен, функция 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?
Получите доступ к макросам через Tools-> Macros-> Macros IDE, затем создайте модуль с именем ClassBreak и вставьте приведенный выше код. Затем вы можете получить доступ к макросу через Tools-> Macros-> Macro Explorer (просто дважды щелкните ClassBreak -> BreakOnAnyMember, чтобы запустить его)
+1. добавьте, пожалуйста, макросы для удаления всех этих точек останова после.
Самое простое решение - выбрать все точки останова для этого файла в «Отладка»> «Windows»> «Точки останова» (или CTRL-D, B) и нажать «Удалить» (X). Если в этом окне не отображаются точки останова, выберите Столбцы> Имя
Если это полезно, в VS08 ввод Ctrl + Shift + F9 удалит все точки останова.
Работал для 2/3 прогонов, а затем завершился неудачно с исключением «как разрешить неопределенную ошибку (исключение из H_RESULT 0x80004005: EFAIL)» в VS2010
@ user1502952 - Единственное, что я могу себе представить, это положение курсора вне класса (или что-то непонятное) или столкновение точек останова.
Возможно, вы могли бы использовать структуру АОП, такую как 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/…
Джоэл, похоже, ответ будет «нет». Невозможно без точки останова для каждого метода.
Чтобы удалить точки останова, установленные принятым ответом, добавьте еще один макрос со следующим кодом
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
Указание языка, с которым вы работаете (Visual Studio может быть C#, C++, Managed C++ или VB.Net), может помочь людям дать вам лучшие предложения.