Break when a value changes using the Visual Studio debugger - visual-studio

Is there a way to place a watch on variable and only have Visual Studio break when that value changes?
It would make it so much easier to find tricky state issues.
Can this be done?
Breakpoint conditions still need a breakpoint set, and I'd rather set a watch and let Visual Studio set the breakpoints at state changes.

In the Visual Studio 2005 menu:
Debug -> New Breakpoint -> New Data Breakpoint
Enter:
&myVariable

You can also choose to break explicitly in code:
// Assuming C#
if (condition)
{
System.Diagnostics.Debugger.Break();
}
From MSDN:
Debugger.Break:
If no debugger is attached, users are
asked if they want to attach a
debugger. If yes, the debugger is
started. If a debugger is attached,
the debugger is signaled with a user
breakpoint event, and the debugger
suspends execution of the process just
as if a debugger breakpoint had been
hit.
This is only a fallback, though. Setting a conditional breakpoint in Visual Studio, as described in other comments, is a better choice.

In Visual Studio 2015, you can place a breakpoint on the set accessor of an Auto-Implemented Property and the debugger will break when the property is updated
public bool IsUpdated
{
get;
set; //set breakpoint on this line
}
Update
Alternatively; #AbdulRaufMujahid has pointed out in the comments that if the auto implemented property is on a single line, you can position your cursor at the get; or set; and hit F9 and a breakpoint will be placed accordingly. Nice!
public bool IsUpdated { get; set; }

Imagine you have a class called A with the following declaration.
class A
{
public:
A();
private:
int m_value;
};
You want the program to stop when someone modifies the value of "m_value".
Go to the class definition and put a breakpoint in the constructor of A.
A::A()
{
... // set breakpoint here
}
Once we stopped the program:
Debug -> New Breakpoint -> New Data Breakpoint ...
Address: &(this->m_value)
Byte Count: 4 (Because int has 4 bytes)
Now, we can resume the program. The debugger will stop when the value is changed.
You can do the same with inherited classes or compound classes.
class B
{
private:
A m_a;
};
Address: &(this->m_a.m_value)
If you don't know the number of bytes of the variable you want to inspect, you can use the sizeof operator.
For example:
// to know the size of the word processor,
// if you want to inspect a pointer.
int wordTam = sizeof (void* );
If you look at the "Call stack" you can see the function that changed the value of the variable.

Change the variable into a property and add a breakpoint in the set method. Example:
private bool m_Var = false;
protected bool var
{
get {
return m_var;
}
set {
m_var = value;
}
}

Update in 2019:
This is now officially supported in Visual Studio 2019 Preview 2 for .Net Core 3.0 or higher. Of course, you may have to put some thoughts in potential risks of using a Preview version of IDE. I imagine in the near future this will be included in the official Visual Studio.
https://blogs.msdn.microsoft.com/visualstudio/2019/02/12/break-when-value-changes-data-breakpoints-for-net-core-in-visual-studio-2019/
Fortunately, data breakpoints are no longer a C++ exclusive because they are now available for .NET Core (3.0 or higher) in Visual Studio 2019 Preview 2!

If you are using WPF, there is an awesome tool : WPF Inspector.
It attaches itself to a WPF app and display the full tree of controls with the all properties, an it allows you (amongst other things) to break on any property change.
But sadly I didn't find any tool that would allow you to do the same with ANY property or variable.

I remember the way you described it using Visual Basic 6.0. In Visual Studio, the only way I have found so far is by specifying a breakpoint condition.

Right click on the breakpoint works fine for me (though mostly I am using it for conditional breakpoints on specific variable values. Even breaking on expressions involving a thread name works which is very useful if you're trying to spot threading issues).

As Peter Mortensen wrote:
In the Visual Studio 2005 menu:
Debug -> New Breakpoint -> New Data Breakpoint
Enter: &myVariable
Additional information:
Obviously, the system must know which address in memory to watch.
So
- set a normal breakpoint to the initialisation of myVariable (or myClass.m_Variable)
- run the system and wait till it stops at that breakpoint.
- Now the Menu entry is enabled, and you can watch the variable by entering &myVariable,
or the instance by entering &myClass.m_Variable. Now the addresses are well defined.
Sorry when I did things wrong by explaining an already given solution. But I could not add a comment, and there has been some comments regarding this.

You can use a memory watchpoint in unmanaged code. Not sure if these are available in managed code though.

You can probably make a clever use of the DebugBreak() function.

You can optionally overload the = operator for the variable and can put the breakpoint inside the overloaded function on specific condition.

Related

Open DTE solution from another program (not add-in)

Is it possible to modify a solution, and use envdte tools, from a command-line project ?
I have an add-in that modifies a solution. But... the changes are required for over a hundred projects... So I'd like to make a c# program that has the same logic, only it iterates through all solution files.
The add-in starts with
EnvDTE.Solution solution = (EnvDTE.Solution)application.Solution;
where DTE2 application is passed from the add-in...
How can I get the same solution, which then I query for projects...
From a separate program, that will only know the solutionPath ?
Is it possible to open the solution, process it, and close it - to move on to the next solution ?
Microsoft gives this example http://msdn.microsoft.com/en-us/library/envdte._solution.open(v=vs.100).aspx
But I don't know what dte is in the context...
Thank you...
VS 2010
edit: I did what the answer below suggests.
Slightly modified, using the link:
http://msdn.microsoft.com/en-us/library/ms228772(v=vs.100).aspx
Thank you
Yes you can. You just need to activate an instance using the COM CLSID for Visual Studio. An example is below. It actually creates a solution and adds two projects to it but the same initialization applies when opening an existing solution.
A couple of caveats:
Mind the COM threading model. The code created from the console app template is sufficient:
[STAThread]
static void Main()
If you have a powerful VS extension like ReSharper installed, you might be better off suspending it if you don't need it for the VS automation. ReSharper had VS commands that control it.
Console.WriteLine("Opening Visual Studio");
var dte = (DTE)Activator.CreateInstance(Type.GetTypeFromProgID("VisualStudio.DTE.10.0",true),true);
Console.WriteLine("Suspending Resharper");
dte.ExecuteCommand("ReSharper_Suspend");
Console.WriteLine("Working with {0}, {1} edition", dte.FullName, dte.Edition);
dte.SuppressUI = true;
dte.UserControl = false;
foreach (var solution in mySolutionInfoList)
{
try
{
dte.Solution.Create(solution.directory, solution.name);
dte.Solution.AddFromTemplate(csharpTemplatePath, solution.directory + "ClassLibrary1", "ClassLibrary1");
dte.Solution.AddFromTemplate(vcTemplatePath, solution.directory + "Win32Dll", "Win32Dll");
Directory.CreateDirectory(solution.directory); // ensure directory exists. Otherwise, user will be asked for save location, regardless of SupressUI value
dte.Solution.Close(true);
Console.WriteLine();
}
catch (Exception e)
{
Console.Error.WriteLine(e);
}
}
Console.WriteLine("Resuming Resharper");
dte.ExecuteCommand("ReSharper_Resume");
try
{
dte.Quit();
}
catch (Exception e)
{
Console.Error.WriteLine(e);
}

Is there a way to prevent Visual Studio from breaking on exceptions in a specific method?

I know I can control the way Visual Studio handles exceptions according to their type and to the fact that they're eventually caught using the "Exception" dialog.
However, I've got a library that's internally throwing (and catching) an ArgumentOutOfRange exception when I'm calling a specific method. The exception is thrown (and caught by the library) maybe 1% of the time, but I'm calling this method a lot. The editor says it's by design (and indeed, the design they've chosen makes sense).
The thing is that I don't want Visual Studio to break each time the exception is thrown.
I don't want to stop breaking on ArgumentOutOfRange exceptions, as I may have some in my code and want to break on those.
I don't want to enable "just my code" debugging because I'm concerned about the exceptions thrown outside of my code (notably for performance reasons)
Is there a way to achieve this? I've been looking into attributes (such as DebuggerStepThrough), but haven't find something adequate yet.
Any hints on how to do this ?
I don't want to enable "just my code" debugging
Yeah, stop there right now. That is exactly the feature you need to not get the unwanted debugger breaks. If you don't want to know about somebody else's crappy code then flip that checkbox back on.
This invariably goes off the rails when programmers use exceptions for flow control. A very common crime. It takes two of them to turn that into a mess that turns a debugging session into a very tedious click nightmare. When you need the debugger feature that breaks on the first-chance exception then you basically lost if somebody else needed that as well.
Everybody hopes that they can magically use the [DebuggerNonUserCode] or [DebuggerHidden] or [DebuggerStepThrough] attributes to make that problem disappear. It doesn't. The other programmer did not think his code was unimportant enough to deserve those attributes. And, well, it wasn't because there's always a bug hidden in code that uses try/catch-em-all code. Pokémon code.
So Microsoft had to find another way to help programmers deal with crappy library code. They did. Tick that checkbox, bam, solved. Nothing you can do about that crappy code anyway, other than sending a nasty-gram to the author. Don't let us or Microsoft slow you down doing that as well, y'all have to get along to create a product that people like to use.
I think it's not possible in visual studio but it certainly is in WinDbg.
See for example http://blogs.msdn.com/b/alejacma/archive/2009/08/24/managed-debugging-with-windbg-breaking-on-an-exception-part-1.aspx
On a side note it seems that starting with visual studio 2010 you can load and use WinDbg extension DLLs directly providing aditional functionality (including possibly the one that you need) but I haven't tried this yet - see for example http://www.dotnetcurry.com/ShowArticle.aspx?ID=648
What you can do is use Concord, the debug engine that ships with Visual Studio (starting with version 2012). It's quite extensible through a nice managed API (and deployable using vsix technology), but it's not fully documented.
Concord has the concept of debug monitors, that we can hook using the IDkmDebugMonitorExceptionNotification Interface
The cool thing is this interface can monitor all exceptions thrown. It can also "suppress" any detected exception event, which is exactly what we need.
What I suggest is to start with the Hello World sample: . Download it, and make sure it runs as expected for you.
Now, just modify HelloWorld.vsdconfigxml like this:
<!--TODO: If you copy the sample, ensure to regenerate the GUID in this file -->
<!-- 1. change component level to something higher than 40500 -->
<ManagedComponent
ComponentId="51736b11-9fb4-4b6d-8aca-a10a2b7ae768"
ComponentLevel="40501"
AssemblyName="HelloWorld">
<!-- 2. change class full name to HelloWorld.ExceptionHandler, for example -->
<Class Name="HelloWorld.ExceptionHandler">
<Implements>
<InterfaceGroup>
<NoFilter/>
<!-- 3. change supported interface -->
<Interface Name="IDkmDebugMonitorExceptionNotification"/>
</InterfaceGroup>
</Implements>
</Class>
</ManagedComponent>
Then, just create an ExceptionHandler.cs class and put something like this in there:
public class ExceptionHandler : IDkmDebugMonitorExceptionNotification
{
private bool _unhandledDetected;
// we're being called!
public void OnDebugMonitorException(DkmExceptionInformation exception, DkmWorkList workList, DkmEventDescriptorS eventDescriptor)
{
if (_unhandledDetected)
{
// this will cause the program to terminate
eventDescriptor.Suppress();
return;
}
if (exception.ProcessingStage.HasFlag(DkmExceptionProcessingStage.Unhandled))
{
_unhandledDetected = true;
}
else if (exception.ProcessingStage.HasFlag(DkmExceptionProcessingStage.Thrown))
{
if (SuppressException(exception))
{
eventDescriptor.Suppress();
}
}
}
// should we suppress a thrown (1st chance) exception?
private bool SuppressException(DkmExceptionInformation exception)
{
// implement any custom logic in here, for example use the exception's name
if (exception.Name == typeof(ArgumentOutOfRangeException).FullName)
{
// for example, use the module (assembly) name
var clrAddress = (DkmClrInstructionAddress)exception.InstructionAddress;
var clrModule = clrAddress.ModuleInstance;
if (clrModule.Name == "TheUglyOne.dll")
return true; // we don't want this one!
}
return false;
}
}
When you run the project, you should see all exceptions being monitored (regardless of your 'just my code' and/or exception triggers settings), so what you just need to do is implement some logic to suppress the ones you really don't want to see. I've not checked but I suppose you could build your logic using custom attributes as the Dkm classes provide quite a lot of .NET metadata information.
Note: as you can see, there is some trickery to make sure the program will terminate normally.

Add item to Error List in Macro

I want to notify the user of the macro if something went wrong during the execution of the macro. I was wondering if it would be possible to add an item to the Visual Studio error list?
It is possible to do so from within an AddIn (like here), but I would like to do the same thing from a macro.
Edit
To further clarify what i want to achive, here is the sample from the Samples macro library (Alt+F8 -> Samples -> Utilities -> SaveView())
Sub SaveView()
Dim name As String
name = InputBox("Enter the name you want to save as:", "Save window layout")
If (name = "") Then
MsgBox("Empty string, enter a valid name.")
Else
DTE.WindowConfigurations.Add(name)
End If
End Sub
Instead of the MsgBox("...") alert I want to put the error into the VS error list.
You can add an item in the Task List easily from your macro. Just use the AddTaskToList method from that article and change m_objDTE to DTE. I've tried it and it worked.
However, adding the item in Error List, is probably impossible. You need to call VS services, see how adding an error is done in an add-in. I created a macro from this code and it didn't work. In general, VS services don't work in macros. I was able to create ErrorListProvider successfully. I could access it's methods and properties. But calling ErrorListProvider.Task.Add caused COM exception. If you want to play with it, several notes:
As described in the article, you need to get 4 assemblies out of the GAC e.g. to c:\dlls\ directory. Since Macros IDE doesn't allow you to browse when you Add Reference, you need to copy these dlls into ...\Microsoft Visual Studio 10.0\Common7\IDE\PublicAssemblies directory (change the 10.0 to your VS version). Then, when you Add Reference in Macros IDE, you should see the assemblies.
The GetService function always returned Nothing. Add the following field to the class:
Private serviceProvider As IServiceProvider = New Microsoft.VisualStudio.Shell.ServiceProvider(CType(DTE, Microsoft.VisualStudio.OLE.Interop.IServiceProvider))
and in GetService function change line:
objService = Microsoft.VisualStudio.Shell.Package.GetGlobalService(serviceType)
to
objService = serviceProvider.GetService(serviceType)
As I wrote, everything seems OK then but ErrorListProvider.Task.Add fails.
I think that for your situation outputting something to your own output pane would be more suitable. The error list is generally used for errors within the project the user is working on, not for errors caused by running macros. Especially when someone says it can't be done. :)
Outputting to your own output pane is pretty easy:
DTE.Windows.Item(Constants.vsWindowKindOutput).Activate()
Dim panes As OutputWindowPanes = window.OutputWindowPanes
Dim my_pane As OutputWindowPane
Try
my_pane = panes.Item("SaveView")
Catch exception As System.ArgumentException
my_pane = panes.Add("SaveView")
End Try
my_pane.Activate()
my_pane.OutputString("Empty string, enter a valid name." + vbCrLf)
Hope this helps.
Cheers,
Sebastiaan
Is this not what you want?
HOWTO: Add an error with navigation to the Error List from a Visual Studio add-in
http://www.mztools.com/articles/2008/MZ2008022.aspx

Copy object values in Visual Studio debug mode

In Visual Studio debug mode it's possible to hover over variables to show their value and then right-click to "Copy", "Copy Expression" or "Copy Value".
In case the variable is an object and not just a basic type, there's a + sign to expand and explore the object. It there a way to copy all that into the clipboard?
In the immediate window, type
?name_of_variable
This will print out everything, and you can manually copy that anywhere you want, or use the immediate window's logging features to automatically write it to a file.
UPDATE: I assume you were asking how to copy/paste the nested structure of the values so that you could either search it textually, or so that you can save it on the side and then later compare the object's state to it. If I'm right, you might want to check out the commercial extension to Visual Studio that I created, called OzCode, which lets you do these thing much more easily through the "Search" and "Compare" features.
UPDATE 2 To answer #ppumkin's question, our new EAP has a new Export feature allows users to Export the variable values to Json, XML, Excel, or C# code.
Full disclosure: I'm the co-creator of the tool I described here.
You can run below code in immediate window and it will export to an xml file the serialized XML representation of an object:
(new System.Xml.Serialization.XmlSerializer(obj.GetType())).Serialize(new System.IO.StreamWriter(#"c:\temp\text.xml"), obj)
Source: Visual Studio how to serialize object from debugger
Most popular answer from https://stackoverflow.com/a/23362097/2680660:
With any luck you have Json.Net in you appdomain already. In which
case pop this into your Immediate window:
Newtonsoft.Json.JsonConvert.SerializeObject(someVariable)
Edit: With .NET Core 3.0, the following works too:
System.Text.Json.JsonSerializer.Serialize(someVariable)
There is a extension called Object Exporter that does this conveniently.
http://www.omarelabd.net/exporting-objects-from-the-visual-studio-debugger/
Extension: https://visualstudiogallery.msdn.microsoft.com/c6a21c68-f815-4895-999f-cd0885d8774f
You can add a watch for that object, and in the watch window, expand and select everything you want to copy and then copy it.
By using attributes to decorate your classes and methods you can have a specific value from your object display during debugging with the DebuggerDisplay attribute e.g.
[DebuggerDisplay("Person - {Name} is {Age} years old")]
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
I always use:
string myJsonString = JsonConvert.SerializeObject(<some object>);
Then I copy the string value which unfortunately also copies the back slashes.
To remove the backlashes go here:
https://www.w3schools.com/jsref/tryit.asp?filename=tryjsref_replace
Then within the <p id="demo">Visit Microsoft!</p> element replace the text with the text you copied.
then replace the var res = str.replace("Microsoft", "W3Schools"); line with
var res = str.replace(/\\/g, '')
Run these new changes but don't forget to click the "try it" button on the right.
Now you should have all the text of the object in json format that you can drop in a json formatter like http://jsonformatter.org or to create a POCO you can now use http://json2csharp.com/
ObjectDumper.NET
This is an awesome way!
You probably need this data for a unit test, so create a Sandbox.cs temporary test or you can create a Console App.
Make sure to get NuGet package, ObjectDumper.NET, not ObjectDumper.
Run this test (or console app)
View test output or text file to get the C# initializer code!
Code:
[TestClass]
public class Sandbox
{
[TestMethod]
public void GetInitializerCode()
{
var db = TestServices.GetDbContext();
var list = db.MyObjects.ToList();
var literal = ObjectDumper.Dump(list, new DumpOptions
{
DumpStyle = DumpStyle.CSharp,
IndentSize = 4
});
Console.WriteLine(literal); // Some test runners will truncate this, so use the file in that case.
File.WriteAllText(#"C:\temp\dump.txt", literal);
}
}
I used to use Object Exporter, but it is 5 years old and no longer supported in Visual Studio. It seems like Visual Studio Extensions come and go, but let's hope this NuGet package is here to stay! (Also it is actively maintained as of this writing.)
Google led me to this 8-year-old question and I ended up using ObjectDumper to achieve something very similar to copy-pasting debugger data. It was a breeze.
I know the question asked specifically about information from the debugger, but ObjectDumper gives information that is basically the same. I'm assuming those who google this question are like me and just need the data for debugging purposes and don't care whether it technically comes from the debugger or not.
I know I'm a bit late to the party, but I wrote a JSON implementation for serializing an object, if you prefer to have JSON output. Uses Newtonsoft.Json reference.
private static void WriteDebugJSON (dynamic obj, string filePath)
{
using (StreamWriter d = new StreamWriter(filePath))
{
d.Write(JsonConvert.SerializeObject(obj));
}
}
I've just right clicked on the variable and selected AddWatch, that's bring up watch window that consists of all the values. I selected all and paste it in a text a text editor, that's all.
Object Dumper is a free and open source extension for Visual Studio and Visual Studio Code.
"Dump as" commands are available via context menu in the Code and Immediate windows.
It's exporting objects to:
C# object initialization code,
JSON,
Visual Basic object initialization code,
XML,
YAML.
I believe that combined with the Diff tool it can be helpful.
I'm the author of this tool.
if you have a list and you want to find a specific variable:
In the immediate window, type
myList.Any(s => s.ID == 5062);
if this returns true
var myDebugVar = myList.FirstOrDefault(s => s.ID == 5062);
?myDebugVar
useful tips here, I'll add my preference for when i next end up here asking this question again in the future.
if you don't mind adding an extension that doesn't require output files or such there's the Hex Visualizer extension for visual studio, by mladen mihajlovic, he's done versions since 2015.
provides a nice display of the array via the usual magnifine glass view object from the local variables window.
https://marketplace.visualstudio.com/items?itemName=Mika76.HexVisualizer2019 is the 2019 version.
If you're in debug mode, you can copy any variable by writing copy() in the debug terminal.
This works with nested objects and also removes truncation and copies the complete value.
Tip: you can right click a variable, and click Copy as Expression and then paste that in the copy-function.
System.IO.File.WriteAllText("b.json", page.DebugInfo().ToJson())
Works great to avoid to deal with string debug format " for quote.
As #OmerRaviv says, you can go to Debug → Windows → Immediate where you can type:
myVariable
(as #bombek pointed out in the comments you don't need the question mark) although as some have found this limits to 100 lines.
I found a better way was to right click the variable → Add Watch, then press the + for anything I wanted to expand, then used #GeneWhitaker's solution, which is Ctrl+A, then copy Ctrl+C and paste into a text editor Ctrl+V.

Is there a way to specify outlining defaults in Visual Studio 2008 so that a file opens up with members collapsed by default?

What I would like to do is have VS2008, when I open a code file, collapse all members of the classes/interfaces in the file by default (including, crucially, any XML documentation and comments).
I do not want to use regions, at all.
I would also like to be able to use the ctrl+m, ctrl+l chord to toggle all member outlining (for example, if everything is collapsed, I would like it to expand all of the members, but not the comments or XML documentation).
Possible? How?
Yes to part 1.
Unsure about part 2.
To have VS2008 automatically open files in a Collapsed state you'll need to create an addin to run the "Edit.CollapsetoDefinition" when each document opens.
This isn't overly tricky - The difficult parts seems to be the that you have to run the code a few milliseconds after the document is actually opened so you need to use the threed pool to do that.
Create an Addin project for VS2008.
Add this code (see following) to the end of the OnConnection Method of the Connect class.
switch (connectMode)
{
case ext_ConnectMode.ext_cm_UISetup:
case ext_ConnectMode.ext_cm_Startup:
//Do nothing OnStartup will be called once IDE is initialised.
break;
case ext_ConnectMode.ext_cm_AfterStartup:
//The addin was started post startup so we need to call its initialisation manually
InitialiseHandlers();
break;
}
Add this method to the Connect class
private void InitialiseHandlers()
{
this._openHandler = new OnOpenHandler(_applicationObject);
}
Add a call to InitialiseHandlers() to the OnStartupComplete method of the Connect class.
public void OnStartupComplete(ref Array custom)
{
InitialiseHandlers();
}
Add this class to the project.
using System;
using System.Collections.Generic;
using System.Text;
using EnvDTE80;
using EnvDTE;
using System.Threading;
namespace Collapser
{
internal class OnOpenHandler
{
DTE2 _application = null;
EnvDTE.Events events = null;
EnvDTE.DocumentEvents docEvents = null;
internal OnOpenHandler(DTE2 application)
{
_application = application;
events = _application.Events;
docEvents = events.get_DocumentEvents(null);
docEvents.DocumentOpened +=new _dispDocumentEvents_DocumentOpenedEventHandler(OnOpenHandler_DocumentOpened);
}
void OnOpenHandler_DocumentOpened(EnvDTE.Document document)
{
if (_application.Debugger.CurrentMode != dbgDebugMode.dbgBreakMode)
{
ThreadPool.QueueUserWorkItem(new WaitCallback(Collapse));
}
}
private void Collapse(object o)
{
System.Threading.Thread.Sleep(150);
_application.ExecuteCommand("Edit.CollapsetoDefinitions", "");
}
}
}
And now all opened files should be fully collapsed.
It would be much easier to use the Visual Studio Macros to do the same thing. Editing the "EnvironmentEvents" Macro file in MyMacros and adding a handler for DocumentEvents.DocumentOpened with :
DTE.ExecuteCommand("Edit.CollapsetoDefinitions")
A quick way to collapse all outlining to function-definitions is to press:
Contextmenu-button*(next to your right windows button)*, L, O
I use it all the time. If there is a real hotkey for this please tell me :)
I had tried working out some Visual Basic code for a macro myself, borrowing from different places, and couldn't get anything to work. So what did I do? Why, I asked a question on StackOverflow of course! It got answered, I added the suggested code to my EnvironmentEvents macro, and now when I open CS files, after about a second, all my definitions are collapsed. :)

Resources