Improved Debugging with Visual Studio 2005's Debugger VisualizersBy Scott Mitchell
When debugging a project in Visual Studio .NET 2002/2003, you can view the current values of a variable by simply entering the value into the Watch window, or by hovering your mouse over the variable in the code window. While this approach worked wonderfully for simple types with short and concise values, the user interface was less than ideal for more complex types or lengthy values. For example, if you were working on an application that manipulated the contents of an XML file you might want to examine the XML string at various points in the application. This would be a challenging task if you had XML content that was more than a few dozen characters long, as Visual Studio .NET would format the XML content in one loooooooong line of text. Kind of made it hard to quickly examine the contents of the XML!
Thankfully the debugger experience in Visual Studio 2005 is much better. In DataTips, Visualizers and Viewers Make Debugging .NET Code a Breeze author Morgan Skinner examines DataTips and Visualizers, two of the nice new debugging features. To summarize, DataTips provide a tooltip-like view of the important properties when in break mode, which you can view and modify. Visualizers present an alternate view of an object or variable in a manner that is more specific to the data type.
Visual Studio 2005 ships with four visualizers, a DataSet visualizer, which shows the contents of a DataSet in a grid, and three text-based visualizers: one for text, one for XML, and one for HTML. The screenshot below shows the XML Visualizer in action, which provides a much more readable view of the XML than simply squishing it all on one line.
What's particularly cool about Visual Studio 2005's debugger visualizers is that the visualizer framework is pluggable. That is, we can create our own custom visualizers and plug them into Visual Studio! In this article we'll look at the basics of debugger visualizers, examine some of the built-in visualizers, look at a few free visualizers developed by various folks in the community, and see how to create our own visualizer! Read on to learn more!
When debugging an application, developers are often interested in the value of certain variables. Visual Studio provides a number of windows - Watch, Autos, Locals, and so on - that provide the current values of various variables. However, these windows' display capabilities are very generic, meaning that regardless of the type of variable being examined, the output is roughly the same. However, for certain types of variables there may be a much more intuitive way to display the value. For example, when viewing the value of a string that contains HTML, rather than just showing the raw markup, a developer might be interested in seeing the markup rendered, as it would appear in a browser.
Visualizers allow for a more type-specific view of a variable during the debugging experience. Visualizers apply to certain types - the Text, HTML, and XML Visualizers, for exmample, apply to string variables. When debugging, you can mouse over such a type in the code window or Watch, Locals, or Autos window and see a little magnifying glass appear. Clicking this will display the value of the variable using the selected visualizer. (For types that support multiple visualizers, such as strings, a drop-down list accompanies the magnifying glass and allows you to select which visualizer to use.)
To illustrate use of the visualizers, create a project in Visual Studio 2005 that has a few string variables. In one, put some valid, XML content; in another, put some HTML content; in the third, put a long string. Next, set a breakpoint in the code and then start debugging. In the Watch window at a reference to the three variables that hold the XML, HTML, and long string values. You'll see a magnifying glass along the right side of each string variable's value, as shown below.
Clicking the magnifying glass will display the selected visualizer. You can choose which visualizer to use by clicking on the little down arrow next to the magnifying glass. In this article's Introduction I showed you the results of the XML Visualizer; below are examples showing the Text and HTML Visualizers.
Dissecting the Visualizer Functionality
At the core, a visualizer has two tasks it must fulfill: first, when given an object instance of a particular type it must be able to take that instance and create a user interface displaying details about that object; second, it must contain the plumbing necessary to interact with the Visual Studio debugger. Part of the challenge in creating a visualizer is that the visualizer runs in two different processes: within the Visual Studio debugger as well as within the running program iteself. A visualizer is implemented as an assembly that includes metadata indicating the particular data type the visualizer is designed to work with. When a developer starts debugging in Visual Studio, the environment loads all of the visualizers and determines what data types they can work with. Then, when the developer mouses over a variable in the code window or Locals, Autos, or Watch windows, Visual Studio displays the magnifying glass icon.
Clicking the magnifying glass icon prompts the visualizer to load this data from the program itself and and pass this data to the visualizer program that resides within the debugger in order to display the data on screen. This passing of data from one portion of the visualizer to the other occurs using binary serialization through streams; the end result is that any objects passed between these partitions of the visualizer must be serializable. Once the visualizer running in the debugger is passed the serialized object to display, it is responsible for creating the user interface that shows the object's value. This likely entails creating a Windows Form and populating its controls with values based on the received object's data.
Extending Visual Studio 2005 with Custom Visualizers
While the four built-in visualizers in Visual Studio are nice, what really makes the visualizer concept useful is that it is pluggable. Developers can create their own custom visualizers and register them with Visual Studio, and registration is as easy as copying a DLL file to a particular directory. Due to the pluggability of visualizers, a number of developers in the community have created free visualizers that you can plug into your copy of Visual Studio.
Some free visualizers (many with source code) worth checking out include:
- Image Debugger Visualizer - this visualizer
allows a developer working with a
Bitmapobject to view the actual image in a dialog box.
- Regex Debugger Visualizer - visualizers for working
with regular expressions. Operates on the String,
- Control Hierarchy Visualizer - K. Scott Allen's visualizer displays the control hierarchy for a Web control in an ASP.NET page; I've also added some features to Scott's code, as discussed in my blog entry Debugging Visualizers in Visual Studio 2005.
- XML Visualizer - view XML documents in a graphical format rather than as markup.
Creating a Custom Visualizer
Creating a custom visualizer typically involves creating three related objects:
- A "visualizer" class - when the developer clicks the magnifying glass during the debugging
session we must somehow reference the corresponding object and display its data in the desired format. The act of
getting the object data from the debugger and passing this data to the user interface is the responsibility of this
visualizer class. This class extends the
DialogDebuggerVisualizerclass and provides a
Show()method that is responsible for grabbing the data and invoking the user interface. This class also should contain the assembly attribute indicating that visualizer's applicable data type.
- A "source" class - the source class's responsibility is to take the object whose magnifying glass was clicked
and pass this object information out of the debugger. This class extends the
VisualizerObjectSourceand provides the
GetData(object, Stream)method to provide a serialized version of the object to the visualizer class. Specifically, the
GetData()method's first input parameter is the object whose magnifying glass icon was clicked; the second input parameter is the
Streamto which the object must be serialized.
- A "user interface" - the user interface by which the data will be displayed. Typically this involves creating a Form (or two), adding the appropriate user interface elements (TextBoxes, TreeViews, etc.), and having the visualizer class pass the user interface the serialized data to display.
System.Web.UI.Pageclass. (You can download this class at the end of this article.)
Let's start by looking at the source class. The
GetData() method here starts by casting the first input parameter
Page object and then dumps the values of the
Request.ServerVariables collection to a new
NameValueCollection. (I do this deep copy because the
Request.NameValueCollection is, underneath the
covers, an object of type
HttpServerVarsCollection, which is not serializable and therefore can't be
ferried from the source class to the visualizer class. The
NameValueCollection is serializable, however, so
after dumping the contents from
Request.NameValueCollection to a local
I then serialize the contents to the
Stream that was passed-in as the second input parameter:
Next, in the visualizer class's
Show() method we deserialize the data from the
method and create the user interface. This is accomplished with the following code:
VisualizerForm class is a Windows Form that contains a ListView control. The
Visualize(NameValueCollection) method (which I wrote), takes the passed-in
object and dumps its contents to the ListView.
Also included in the visualizer class is the
DebuggerVisualizer attribute, which wires up the visualizer to the
System.Web.UI.Page data type:
Deploying and Testing the Custom Visualizer
Once you've successfully built the custom visualizer, deployment is a breeze. Simply copy the assembly (the DLL file) to the
My Documents\Visual Studio 2005\Visualizersfolder. That's it! To test the visualizer out, open up Visual Studio 2005, create a new website project and set a breakpoint in the code. Next, start the debugger. When you hit the breakpoint, type into the Watch window
thisin C# or
Mein VB). You should see a little magnifying glass icon in the Watch window. Click on this and you should see the dialog box shown below. If you select a particular item from the ListView, you'll be shown a detailed view.
One of the pains of developing visualizers is testing/debugging the visualizer. The only sure-fire way to ensure that you
have the full debugger experience is to build your visualizer assembly, manually copy it to the Visual Studio 2005
Visualizers directory, launch VS, and start debugging. If you find a mistake or want to make a change you need
to stop debugging, close Visual Studio, make the change to the visualizer, recompile, recopy the file to the
directory, relaunch VS, and return to debugging. Ick.
There is another, more efficient way that you can use that actually allows you to step into the visualizer code through the
debugger. This technique involves creating a stand-alone Console Application, as discussed in
Creating a Debugger Visualizer Using Visual Studio 2005 Beta 2.
The only downside is that since you are not really running the application, you have to simulate the serialized object from
the source class, which means you'll be missing out on request-specific information that you would have when actually debugging.
(This is more of an issue when working with ASP.NET instrinsic controls, like the
Visual Studio 2005 has improved the developer's experience in many ways, one of which has been an improved debugging experience. One of the cool new debugging features in Visual Studio 2005 is the debugger visualizers, which provide a custom way to view specific data types. Visual Studio ships with four built-in visualizers, but there are plenty of community-created visualizers and the architecture exists to easily create our own custom visualizers. In this article we looked at the visualizer model, three of the four built-in visualizers, a number of community-created visualizers, and even saw how to create our own visualizer.