<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Scott Beaudreau's Weblog : Development</title><link>http://blogs.msdn.com/scott_beaudreau/archive/tags/Development/default.aspx</link><description>Tags: Development</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>Raising the Bar on DebuggerVisualizers</title><link>http://blogs.msdn.com/scott_beaudreau/archive/2005/04/28/413004.aspx</link><pubDate>Thu, 28 Apr 2005 17:19:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:413004</guid><dc:creator>Scott Beaudreau</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/scott_beaudreau/comments/413004.aspx</comments><wfw:commentRss>http://blogs.msdn.com/scott_beaudreau/commentrss.aspx?PostID=413004</wfw:commentRss><description>I found a number of interesting links to solid work around debugger visualizers. Scott Nonnenberg has an excellent blog with quite a few posts around this topic. He's a PM on the Debugging group within Visual Studio. Scott's building an index of debugger visualizer entries, and some of them are very compelling....(&lt;a href="http://blogs.msdn.com/scott_beaudreau/archive/2005/04/28/413004.aspx"&gt;read more&lt;/a&gt;)&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=413004" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/scott_beaudreau/archive/tags/General/default.aspx">General</category><category domain="http://blogs.msdn.com/scott_beaudreau/archive/tags/Development/default.aspx">Development</category></item><item><title>Developing an DebuggerVisualizer for Images</title><link>http://blogs.msdn.com/scott_beaudreau/archive/2005/04/26/412301.aspx</link><pubDate>Tue, 26 Apr 2005 23:48:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:412301</guid><dc:creator>Scott Beaudreau</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/scott_beaudreau/comments/412301.aspx</comments><wfw:commentRss>http://blogs.msdn.com/scott_beaudreau/commentrss.aspx?PostID=412301</wfw:commentRss><description>&lt;P&gt;I have been working with Visual Studio 2005 Beta 2 quite a bit.&amp;nbsp; One of the more compelling debugging features in VS2005 Beta 2 is the ability to create new extensions to the debugger for supporting custom visualization of objects that are being inspected.&amp;nbsp; The basic object types in .NET are already supported by the debugger, but sometimes it can be useful to inspect an object type in a visually customized way, depending on the type of object.&amp;nbsp; Some examples might be:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Visualize business objects in a rich, application-specific manner 
&lt;LI&gt;Visualize RegEx objects at debug time in a way that allows you to interact with them 
&lt;LI&gt;Visualize an Image object at debug time that you might have loaded from disk or via a network call 
&lt;LI&gt;Visualize a custom shape object type used in a 3D Game engine 
&lt;LI&gt;Visualize Windows handle objects and examine details associated with them&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;Visual Studio 2005 allows you to extend your debugger's visualization capabilities by creating a new &lt;A title="MSDN information on the DebuggerVisualizer class" href="http://msdn.microsoft.com/msdnmag/issues/04/05/VisualStudio2005Debugging/default.aspx" target=_blank&gt;DebuggerVisualizer&lt;/A&gt; class.&amp;nbsp; This class simply registers itself with an appropriate assembly-level attribute, and when it is invoked by the debugger, it displays a custom form, control, or dialog that can render the passed type.&amp;nbsp; It must be installed in a specific subfolder at either the user or the machine level.&amp;nbsp; It's simple enough that you can build one in 5 minutes.&lt;/P&gt;
&lt;H1&gt;Building a DebuggerVisualizer in 5 minutes&lt;/H1&gt;
&lt;P&gt;While on the plane coming home from London this weekend, I built a debugger visualizer for Images.&amp;nbsp; I earlier read an &lt;A title="DevX Article: Creating Debugger Visualizers with Visual Studio 2005" href="http://www.devx.com/codemag/Article/27821/1954?pf=true"&gt;article&lt;/A&gt; in DevX from Julia Lerman that was very helpful with regard to debugger visualizers in general.&amp;nbsp; There have been some minor changes since Beta 1 in this area, and the process seems to be even easier now.&lt;/P&gt;
&lt;P&gt;There are only a few simple steps to building a basic debugger visualizer.&amp;nbsp; First, you create a new solution as a class library.&amp;nbsp; You then create a class that derives from &lt;SPAN class=symbol&gt;DebuggerVisualizer&lt;/SPAN&gt;, override it's &lt;SPAN class=symbol&gt;Show()&lt;/SPAN&gt; method, and add an assembly-level attribute that VS 2005 will look for when it starts a debugging session.&amp;nbsp; The next step is to create a custom Form object to display the object that is being inspected during debugging.&amp;nbsp; Finally, you compile it all and copy the assembly to a special directory.&amp;nbsp; That's it-- you can probably implement one in less than 5 minutes.&amp;nbsp; I will walk through the steps in detail now.&amp;nbsp; Alternately, you can download my &lt;A title="Download of my implementation" href="http://www.matrixreality.net/blog/download/GDIDebugVisualizers.zip"&gt;project&lt;/A&gt; if you wish.&lt;/P&gt;
&lt;H2&gt;Step 1: Create a new project as a C# class library&lt;/H2&gt;
&lt;P&gt;Create a new project within Visual Studio 2005 Beta 2 as a C# class library with a name of &lt;SPAN class=symbol&gt;GDIDebugVisualizers&lt;/SPAN&gt;.&amp;nbsp; Delete the &lt;SPAN class=filepath&gt;Class1.cs&lt;/SPAN&gt; file that was added.&lt;/P&gt;
&lt;H2&gt;Step 2: Add a DebuggerVisualizer item to the project&lt;/H2&gt;
&lt;P&gt;Right-click on the new project and select Add -&amp;gt; New Item.&amp;nbsp; Choose the DebuggerVisualizer item type, and give it a name of &lt;SPAN class=filepath&gt;ImageDebuggerVisualizer.cs&lt;/SPAN&gt;.&amp;nbsp; The new class should look like the code block below:&lt;/P&gt;
&lt;DIV class=csharpcode&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   1:  &lt;/SPAN&gt;&lt;SPAN class=kwrd&gt;using&lt;/SPAN&gt; System;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   2:  &lt;/SPAN&gt;&lt;SPAN class=kwrd&gt;using&lt;/SPAN&gt; System.Collections.Generic;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   3:  &lt;/SPAN&gt;&lt;SPAN class=kwrd&gt;using&lt;/SPAN&gt; System.Windows.Forms;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   4:  &lt;/SPAN&gt;&lt;SPAN class=kwrd&gt;using&lt;/SPAN&gt; Microsoft.VisualStudio.DebuggerVisualizers;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   5:  &lt;/SPAN&gt;&amp;nbsp;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   6:  &lt;/SPAN&gt;&lt;SPAN class=kwrd&gt;namespace&lt;/SPAN&gt; GDIDebuggerVisualizers&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   7:  &lt;/SPAN&gt;{&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   8:  &lt;/SPAN&gt;    &lt;SPAN class=rem&gt;// TODO: Add the following to SomeType's defintion to see this visualizer &lt;/SPAN&gt;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   9:  &lt;/SPAN&gt;    &lt;SPAN class=rem&gt;//       when debugging instances of SomeType:&lt;/SPAN&gt;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  10:  &lt;/SPAN&gt;    &lt;SPAN class=rem&gt;// &lt;/SPAN&gt;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  11:  &lt;/SPAN&gt;    &lt;SPAN class=rem&gt;//  [DebuggerVisualizer(typeof(ImageDebuggerVisualizer))]&lt;/SPAN&gt;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  12:  &lt;/SPAN&gt;    &lt;SPAN class=rem&gt;//  [Serializable]&lt;/SPAN&gt;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  13:  &lt;/SPAN&gt;    &lt;SPAN class=rem&gt;//  public class SomeType&lt;/SPAN&gt;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  14:  &lt;/SPAN&gt;    &lt;SPAN class=rem&gt;//  {&lt;/SPAN&gt;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  15:  &lt;/SPAN&gt;    &lt;SPAN class=rem&gt;//   ...&lt;/SPAN&gt;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  16:  &lt;/SPAN&gt;    &lt;SPAN class=rem&gt;//  }&lt;/SPAN&gt;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  17:  &lt;/SPAN&gt;    &lt;SPAN class=rem&gt;// &lt;/SPAN&gt;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  18:  &lt;/SPAN&gt;    &lt;SPAN class=rem&gt;/// &amp;lt;summary&amp;gt;&lt;/SPAN&gt;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  19:  &lt;/SPAN&gt;    &lt;SPAN class=rem&gt;/// A Visualizer for SomeType.  &lt;/SPAN&gt;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  20:  &lt;/SPAN&gt;    &lt;SPAN class=rem&gt;/// &amp;lt;/summary&amp;gt;&lt;/SPAN&gt;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  21:  &lt;/SPAN&gt;    &lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;class&lt;/SPAN&gt; ImageDebuggerVisualizer : DialogDebuggerVisualizer&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  22:  &lt;/SPAN&gt;    {&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  23:  &lt;/SPAN&gt;        &lt;SPAN class=kwrd&gt;protected&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;override&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;void&lt;/SPAN&gt; Show(IDialogVisualizerService windowService, &lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  24:  &lt;/SPAN&gt;                                     IVisualizerObjectProvider objectProvider)&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  25:  &lt;/SPAN&gt;        {&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  26:  &lt;/SPAN&gt;            &lt;SPAN class=rem&gt;// TODO: Get the object to display a visualizer for.&lt;/SPAN&gt;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  27:  &lt;/SPAN&gt;            &lt;SPAN class=rem&gt;//       Cast the result of objectProvider.GetObject() &lt;/SPAN&gt;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  28:  &lt;/SPAN&gt;            &lt;SPAN class=rem&gt;//       to the type of the object being visualized.&lt;/SPAN&gt;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  29:  &lt;/SPAN&gt;            &lt;SPAN class=kwrd&gt;object&lt;/SPAN&gt; data = (&lt;SPAN class=kwrd&gt;object&lt;/SPAN&gt;)objectProvider.GetObject();&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  30:  &lt;/SPAN&gt;&amp;nbsp;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  31:  &lt;/SPAN&gt;            &lt;SPAN class=rem&gt;// TODO: Display your view of the object.&lt;/SPAN&gt;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  32:  &lt;/SPAN&gt;            &lt;SPAN class=rem&gt;//       Replace displayForm with your own custom Form or Control.&lt;/SPAN&gt;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  33:  &lt;/SPAN&gt;            &lt;SPAN class=kwrd&gt;using&lt;/SPAN&gt; (Form displayForm = &lt;SPAN class=kwrd&gt;new&lt;/SPAN&gt; Form())&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  34:  &lt;/SPAN&gt;            {&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  35:  &lt;/SPAN&gt;                displayForm.Text = data.ToString();&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  36:  &lt;/SPAN&gt;                windowService.ShowDialog(displayForm);&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  37:  &lt;/SPAN&gt;            }&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  38:  &lt;/SPAN&gt;        }&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  39:  &lt;/SPAN&gt;&amp;nbsp;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  40:  &lt;/SPAN&gt;        &lt;SPAN class=rem&gt;// TODO: Add the following to your testing code to test the visualizer:&lt;/SPAN&gt;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  41:  &lt;/SPAN&gt;        &lt;SPAN class=rem&gt;// &lt;/SPAN&gt;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  42:  &lt;/SPAN&gt;        &lt;SPAN class=rem&gt;//    ImageDebuggerVisualizer.TestShowVisualizer(new SomeType());&lt;/SPAN&gt;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  43:  &lt;/SPAN&gt;        &lt;SPAN class=rem&gt;// &lt;/SPAN&gt;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  44:  &lt;/SPAN&gt;        &lt;SPAN class=rem&gt;/// &amp;lt;summary&amp;gt;&lt;/SPAN&gt;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  45:  &lt;/SPAN&gt;        &lt;SPAN class=rem&gt;/// Tests the visualizer by hosting it outside of the debugger.&lt;/SPAN&gt;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  46:  &lt;/SPAN&gt;        &lt;SPAN class=rem&gt;/// &amp;lt;/summary&amp;gt;&lt;/SPAN&gt;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  47:  &lt;/SPAN&gt;        &lt;SPAN class=rem&gt;/// &amp;lt;param name="objectToVisualize"&amp;gt;The object to display in the visualizer.&amp;lt;/param&amp;gt;&lt;/SPAN&gt;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  48:  &lt;/SPAN&gt;       &lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;static&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;void&lt;/SPAN&gt; TestShowVisualizer(&lt;SPAN class=kwrd&gt;object&lt;/SPAN&gt; objectToVisualize)&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  49:  &lt;/SPAN&gt;        {&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  50:  &lt;/SPAN&gt;            VisualizerDevelopmentHost visualizerHost = &lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  51:  &lt;/SPAN&gt;                &lt;SPAN class=kwrd&gt;new&lt;/SPAN&gt; VisualizerDevelopmentHost(objectToVisualize, &lt;SPAN class=kwrd&gt;typeof&lt;/SPAN&gt;(ImageDebuggerVisualizer));&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  52:  &lt;/SPAN&gt;            visualizerHost.ShowVisualizer();&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  53:  &lt;/SPAN&gt;        }&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  54:  &lt;/SPAN&gt;    }&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  55:  &lt;/SPAN&gt;}&lt;/PRE&gt;&lt;/DIV&gt;&lt;BR&gt;
&lt;H2&gt;Step 3: Create an custom form for visualization&lt;/H2&gt;
&lt;P&gt;This is the most interesting part because it is where you render the debug-time object visually.&amp;nbsp; Simply add a new Form object to the project and call it &lt;SPAN class=filepath&gt;ImageFormViewer.cs&lt;/SPAN&gt;.&amp;nbsp; In the designer, change the &lt;SPAN class=symbol&gt;FormBorderStyle&lt;/SPAN&gt; to &lt;SPAN class=symbol&gt;FormBorderStyle.SizableToolWindow&lt;/SPAN&gt;.&amp;nbsp; Next add a PictureBox control to the new form, configure it's &lt;SPAN class=symbol&gt;Dock&lt;/SPAN&gt; property to &lt;SPAN class=symbol&gt;DockStyle.Fill&lt;/SPAN&gt;, and set it's &lt;SPAN class=symbol&gt;SizeMode&lt;/SPAN&gt; property to &lt;SPAN class=symbol&gt;PictureBoxSizeMode.Zoom&lt;/SPAN&gt;.&amp;nbsp; See the diagram below:&lt;/P&gt;
&lt;P&gt;&lt;IMG src="http://www.matrixreality.net/blog/Images/ImageVisualizerForm.jpg"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;
&lt;P&gt;Finally, add a new property to this &lt;SPAN class=symbol&gt;ImageFormViewer&lt;/SPAN&gt; class called &lt;SPAN class=symbol&gt;CurrentImage&lt;/SPAN&gt;, implementing get and set in a way that directly returns the picturebox's &lt;SPAN class=symbol&gt;Image&lt;/SPAN&gt; object.&amp;nbsp; See the code snippet below:&lt;/P&gt;
&lt;DIV class=csharpcode&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   1:  &lt;/SPAN&gt;&lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt; Image CurrentImage&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   2:  &lt;/SPAN&gt;{&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   3:  &lt;/SPAN&gt;   get { &lt;SPAN class=kwrd&gt;return&lt;/SPAN&gt; currentPicture.Image; }&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   4:  &lt;/SPAN&gt;   set { currentPicture.Image = value; }&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   5:  &lt;/SPAN&gt;}&lt;/PRE&gt;&lt;/DIV&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;H2&gt;Step 4: Modify the code to use the new ImageFormViewer form&lt;/H2&gt;
&lt;P&gt;Remove the TODO comments after following the instructions, and add the logic to load the custom form.&amp;nbsp; You will somehow need to send the object itself to this form.&amp;nbsp; The end result should be something that looks like this:&lt;/P&gt;
&lt;DIV class=csharpcode&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   1:  &lt;/SPAN&gt;&lt;SPAN class=kwrd&gt;using&lt;/SPAN&gt; System;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   2:  &lt;/SPAN&gt;&lt;SPAN class=kwrd&gt;using&lt;/SPAN&gt; System.Collections.Generic;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   3:  &lt;/SPAN&gt;&lt;SPAN class=kwrd&gt;using&lt;/SPAN&gt; System.Windows.Forms;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   4:  &lt;/SPAN&gt;&lt;SPAN class=kwrd&gt;using&lt;/SPAN&gt; System.Drawing;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   5:  &lt;/SPAN&gt;&lt;SPAN class=kwrd&gt;using&lt;/SPAN&gt; Microsoft.VisualStudio.DebuggerVisualizers;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   6:  &lt;/SPAN&gt;&amp;nbsp;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   7:  &lt;/SPAN&gt;[assembly: System.Diagnostics.DebuggerVisualizer(&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   8:  &lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;typeof&lt;/SPAN&gt;(GDIDebuggerVisualizers.ImageDebuggerVisualizer), &lt;SPAN class=kwrd&gt;typeof&lt;/SPAN&gt;(VisualizerObjectSource), &lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   9:  &lt;/SPAN&gt; Target = &lt;SPAN class=kwrd&gt;typeof&lt;/SPAN&gt;(System.Drawing.Image), Description = &lt;SPAN class=str&gt;"Image Visualizer"&lt;/SPAN&gt;)]&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  10:  &lt;/SPAN&gt;&amp;nbsp;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  11:  &lt;/SPAN&gt;&lt;SPAN class=kwrd&gt;namespace&lt;/SPAN&gt; GDIDebuggerVisualizers&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  12:  &lt;/SPAN&gt;{&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  13:  &lt;/SPAN&gt;    &lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;class&lt;/SPAN&gt; ImageDebuggerVisualizer : DialogDebuggerVisualizer&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  14:  &lt;/SPAN&gt;    {&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  15:  &lt;/SPAN&gt;        &lt;SPAN class=kwrd&gt;protected&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;override&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;void&lt;/SPAN&gt; Show(IDialogVisualizerService windowService, &lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  16:  &lt;/SPAN&gt;                                     IVisualizerObjectProvider objectProvider)&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  17:  &lt;/SPAN&gt;        {&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  18:  &lt;/SPAN&gt;            Image debugImage = objectProvider.GetObject() &lt;SPAN class=kwrd&gt;as&lt;/SPAN&gt; Image;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  19:  &lt;/SPAN&gt;            &lt;SPAN class=kwrd&gt;if&lt;/SPAN&gt; (debugImage != &lt;SPAN class=kwrd&gt;null&lt;/SPAN&gt;)&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  20:  &lt;/SPAN&gt;            {&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  21:  &lt;/SPAN&gt;                &lt;SPAN class=kwrd&gt;using&lt;/SPAN&gt; (ImageViewerForm displayForm = &lt;SPAN class=kwrd&gt;new&lt;/SPAN&gt; ImageViewerForm())&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  22:  &lt;/SPAN&gt;                {&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  23:  &lt;/SPAN&gt;                    displayForm.CurrentImage = debugImage;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  24:  &lt;/SPAN&gt;                    DialogResult result = windowService.ShowDialog(displayForm);&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  25:  &lt;/SPAN&gt;                    &lt;SPAN class=kwrd&gt;if&lt;/SPAN&gt; (result == DialogResult.OK)&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  26:  &lt;/SPAN&gt;                    {&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  27:  &lt;/SPAN&gt;                        objectProvider.ReplaceObject(displayForm.CurrentImage);&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  28:  &lt;/SPAN&gt;                    }&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  29:  &lt;/SPAN&gt;                }&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  30:  &lt;/SPAN&gt;            }&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  31:  &lt;/SPAN&gt;        }&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  32:  &lt;/SPAN&gt;&amp;nbsp;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  33:  &lt;/SPAN&gt;       &lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;static&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;void&lt;/SPAN&gt; TestShowVisualizer(&lt;SPAN class=kwrd&gt;object&lt;/SPAN&gt; objectToVisualize)&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  34:  &lt;/SPAN&gt;        {&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  35:  &lt;/SPAN&gt;            VisualizerDevelopmentHost visualizerHost = &lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  36:  &lt;/SPAN&gt;                &lt;SPAN class=kwrd&gt;new&lt;/SPAN&gt; VisualizerDevelopmentHost(objectToVisualize, &lt;SPAN class=kwrd&gt;typeof&lt;/SPAN&gt;(ImageDebuggerVisualizer));&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  37:  &lt;/SPAN&gt;            visualizerHost.ShowVisualizer();&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  38:  &lt;/SPAN&gt;        }&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  39:  &lt;/SPAN&gt;    }&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  40:  &lt;/SPAN&gt;}&lt;/PRE&gt;&lt;/DIV&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;H2&gt;Step 5: Compile and Deploy&lt;/H2&gt;
&lt;P&gt;You can install the new visualizer assembly at a user level or at a machine level.&amp;nbsp; For the user-level approach, copy the compiled assembly to:&amp;nbsp; &lt;SPAN class=filepath&gt;My Documents\Visual Studio 2005\Visualizers&lt;/SPAN&gt;.&amp;nbsp; For a machine-wide approach, copy the assembly to:&amp;nbsp; &lt;SPAN class=filepath&gt;\Program Files\Microsoft Visual Studio 8\Common7\Packages\Debugger\Visualizers&lt;/SPAN&gt;.&amp;nbsp; Once this has been copied, you are ready to debug.&amp;nbsp; In Beta 2, no restart is required because VS 2005 will check for the available visualizers every time you start a debug session.&amp;nbsp; Of course, you cannot change the list of registered Debugger Visualizers &lt;EM&gt;during&lt;/EM&gt; a debug session.&lt;/P&gt;
&lt;H1&gt;Test with the Debugger&lt;/H1&gt;
&lt;P&gt;Testing simply requires that you start a debugging session and inspect an Image object.&amp;nbsp; The easiest way is to build a simple WinForm application with a PictureBox control configured at design-time to load an external bitmap file.&amp;nbsp; The result will look like the picture below:&lt;/P&gt;
&lt;P&gt;&lt;IMG src="http://www.matrixreality.net/blog/Images/TestApp.jpg"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Insert a breakpoint in the code, and start debugging.&amp;nbsp; When you hit the breakpoint, inspect the picturebox Image property by hovering over it.&amp;nbsp; There should be a magnifying glass icon that appears, with a drop-down associated for the new Debugger Visualization.&amp;nbsp; The screenshots below show this in action:&lt;/P&gt;
&lt;P&gt;&lt;IMG src="http://www.matrixreality.net/blog/Images/DebuggingSnippet1.jpg" border=1&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;When you clock on the Image Visualizer in the drop-down menu, your new Debugger Visualizer is launched.&amp;nbsp; The screenshot below shows this using my implementation (I support a context menu for loading and saving images as well).&amp;nbsp;&lt;/P&gt;
&lt;P&gt;
&lt;P&gt;&lt;IMG src="http://www.matrixreality.net/blog/Images/DebuggingSnippet2.jpg" border=1&gt;&amp;nbsp;&lt;/P&gt;
&lt;H1&gt;Testing without Debugging&lt;/H1&gt;
&lt;P&gt;There is a way of testing out the visualizer without actually debugging by using an instance of &lt;SPAN class=symbol&gt;VisualizerDevelopmentHost&lt;/SPAN&gt;.&amp;nbsp; This class invokes the visualizer as if it were in a debugging session, and is for testing purposes.&amp;nbsp; The template-generated code from Lines 50-52 of the code for Step 2 implements this approach via a static method.&amp;nbsp; You can create a simple project in the same solution, add a project reference to the visualizer, and call the static method to test this out.&amp;nbsp; Don't forget to add a reference to the &lt;SPAN class=symbol&gt;Microsoft.VisualStudio.DebuggerVisualizers&lt;/SPAN&gt; assembly in this test project-- you need this reference because the visualizer depends on it.&amp;nbsp;&lt;/P&gt;
&lt;H1&gt;Other Notes&lt;/H1&gt;
&lt;P&gt;There are some important things to know about DebuggerVisualizer implementations.&amp;nbsp; I received some updates from Scott Nonnenberg as well&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;You can have &lt;EM&gt;one&lt;/EM&gt; or &lt;EM&gt;more&lt;/EM&gt; System.Diagnostics.DebuggerVisualizer attributes per assembly. 
&lt;LI&gt;You need &lt;EM&gt;an&lt;/EM&gt; instance of the System.Diagnostics.DebuggerVisualizer for every type your visualizer supports (can be multiple here). 
&lt;LI&gt;You can have multiple debugger visualizers implemented within an assembly.&amp;nbsp; 
&lt;LI&gt;This form implementation can be smart enough to handle different types which are semantically similar but taxonomically distinct. 
&lt;LI&gt;You can support changes to the object by calling the &lt;SPAN class=symbol&gt;ReplaceObject()&lt;/SPAN&gt; method of the &lt;SPAN class=symbol&gt;IVisualizerObjectProvider&lt;/SPAN&gt; (examine the &lt;SPAN class=symbol&gt;DialogResult&lt;/SPAN&gt; first). &lt;/LI&gt;&lt;/UL&gt;
&lt;H1&gt;Next Steps&lt;/H1&gt;
&lt;P&gt;In any case, this was an interim step, and I am thinking about building more interesting debugger visualizers now.&amp;nbsp; The most compelling implementations to me would probably be some sort of Web Services debugger visualizer.&amp;nbsp; I will look around for other more sophisticated debugger visualizers when I get a chance.&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;&lt;EM&gt;This posting is provided "AS IS" with no warranties, and confers no rights.&lt;/EM&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=412301" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/scott_beaudreau/archive/tags/General/default.aspx">General</category><category domain="http://blogs.msdn.com/scott_beaudreau/archive/tags/Development/default.aspx">Development</category></item></channel></rss>