Search
Friday, March 02, 2001 ..:: Home ::.. Register  Login
   Calendar  
     
  
   Search  
     
  
   Disclosure  
     
  
   TechTidBits (Blog)  

Visual Studio Debugger Visualizers are VERY cool! You gotta check this out!

Oct 25

Written by:
Sunday, October 25, 2009 8:37 PM  RssIcon

Bold title eh?  Ya, I thought so too but it's true!  If you haven't tried Visual Studio's Debugger Visualizers, you're missing out!  Read on for a gripping intro!

While preparing for an upcoming ODNC Visual Studio TnT (Tips'n'Tricks), SG suggested I talk about VS Debugger Visualizers.  hhhmm I heard of them but never really paid them much attention.  Man, was I missing out on something HUGE!!!!!  Visual Studio's Debugger Visualizers are an easy way to create a custom view on your own class when you're debugging.  Yup, you can put your own face on your own custom classes!  Now THAT's cool I think! 

We create one or two classes a day right?  HMPH! you say?  Ya, thought so, you're probably creating quite a few and over the course of a week you might have created a hundred (or MORE!).  But how do you debug into them?  You set a break point and let the default debugger do the rest right?  VS' debugger is going to do a ToString() on your objects to give you what you desire.  That sounds kind of over simplistic for some complex object that took you all day to create if you ask me!  Oh sorry, you didn't ask.....yet that is, I'm sure you're asking it now?! haha

What's the big deal you ask?  Well, if you think the Locals, or the Autos or the Watch windows are good enough, then thank you for your time and good bye.  So long.  BUT, if you think there should be more, if you think you SHOULD be able to tell VS how to display your own classes, then we're on the same brainwave and please continue reading!

Need a bit more context?  (Glad you're still here!)  Here's an example of what I'm talking about.  I whipped up a class called GPSPosition, it has, well, as you can see below, an Address, Description, GoogleMapsLink, Latitude, Longitude and Photo properties (each with appropriately data types).  BUT if you/me/anyone using my app would like to put a context around this class.....well.....you'd be SOL unfortunately.  Wouldn't it be nice, or even COOL if, as you're debugging you could SEE what the original class designer really intended?  Wouldn't it be cool to SEE that Photo as an image?  What about seeing the actual Google Maps view?  THAT would be cool!  If you think so too, then you're at the right place and I hope you keep reading!

Below, I enumerated the different default ways VS gives you to debug into a variable, mainly hovering over the variable, using the QuickWatch window and the using the Autos and Locals windows.

Classic Class Debugging

Default classic debugging

Quick Watch Window (SHFT+F9)

Debugging with QuickWatch

Debugging With Autos (CTRL+D, A)

Debugging with Autos

Debugging with Locals (CTRL+D, L)

Debugging with Locals

With Visual Studio, you can put "lipstick" on your own classes.  A brief overview of what you need to do is, you

  • create one form to show off your custom class (Labels, TextBoxes, DataGrids, go nuts!)
  • create one class, decorate it with one attribute
    • override a Show method
    • cast one of the incoming parameters to your custom class
    • set the controls on your form
    • ShowDialog()

When you do aaaaaaaaaall that, you'll see something similar to this (milage may vary according to number of coffees drank today).

Starting to show custom visualizer

Viewing custom visualizer

THAT'S IT!!!!!!!!!!!  THAT'S ALL THERE IS TO IT!  OK, ok, there are some minor gotchas, but they aren't impossible and not too earth shattering.

So, let's start, first off, start VS with admin privs!

Start VS with Administrator privileges

Next create a solution, with a Windows Application output type.  This is going to be our core piece of code, this is where we'll create our class we want to do some of that fancy "Business Logic" on! LOL  This is the class we're going to use to test our upcoming visualizer.  Ok, go ahead and create something like this.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;

namespace PCHenry.ExploreLatLong
{
  [Serializable]
  public class GPSPosition
  {
    public double Latitude
    {
      get;
      private set;
    }
    public double Longitude
    {
      get;
      private set;
    }
    public string Description
    {
      get;
      private set;
    }
    public string Address
    {
      get;
      private set;
    }
    public Image Photo
    {
      get;
      private set;
    }

    public Uri GoogleMapsLink
    {
      get
      {
        return new Uri( string.Format( "http://maps.google.com/maps?q={0},{1}&z=19", Latitude, Longitude ) );
      }
    }

    public GPSPosition( double latitude, double longitude, string description, string address ) :
      this( latitude, longitude, description, address, null )
    {
    }

    public GPSPosition( double latitude, double longitude, string description, string address, Image photo )
    {
      this.Latitude = latitude;
      this.Longitude = longitude;
      this.Description = description;

      if( !string.IsNullOrEmpty( address ) )
      {
        this.Address = address;
      }

      if( photo != null )
      {
        this.Photo = photo;
      }
    }

    public override string ToString()
    {
      return string.Format( "{0} @ \t({1}, {2})", Description, Latitude, Longitude );
    }
  }
}

Make sure you put the [Serializable] attribute as the class decorator.  If you forget, weeeeeeeell, that's ok, cause the compiler will remind you!  HAHA

Next, design the main application's form.  Mine looks like this (ain't it pertty?  hey, I never claimed to be a graphics designer!). LOL

Main application form in design mode

OK, at this point, compile it, debug it, run it, ooops, test it and change it, run, test, change, compile, rinse, repeat.  Let's do this the old fashioned way.  Hey, it's the last time you're going to do this, so let's just do it for old time sake ok?  DOH!

Now we're going to add our "Debugger Visualizer" part, the really cool part. 

Add a new project to your solution, but this time add an output type of Class Library.  We want this to be a DLL.  This DLL is going to be copied to a special place so Visual Studio can see and use it, but let's not get too far ahead of ourselves yet.

Add a Windows Form to your Class Library project (example below is what I'm using).  I know, I know, it looks an aweful lot like the one above, just add a bit of flavour to yours (I added the ability to click the image to launch the actual URL in a browser). 

 Debugger Visualizer main form

The key to this new class is to create a constructor that takes an object that you juuuuuuuust created above in the other project.  Yup, you'll need to add a reference to your other project (which is why we did that one first).  Next, while we're adding in references, add in Microsoft.VisualStudio.DebuggerVisualizers.  We'll need that in the next step.

Adding reference to the DebuggerVisualizers

Next is where the REAL magic happens (ya, ya, about time, I know, I know, all that other stuff was to make this anti-climatic, and just work).  Add a new class to your class library, and this time, extend the DialogDebuggerVisualizer class.  Next, add in a DebuggerVisualizer attribute (details coming), and then override the Show method.  In other words.....

using System;
using System.Diagnostics;
using Microsoft.VisualStudio.DebuggerVisualizers;
using PCHenry.ExploreLatLong;

[assembly: DebuggerVisualizer( typeof( PCHenry.Debugger.Visualizer.GPSPositionVisualizer ),
  typeof( VisualizerObjectSource ),
  Target = typeof( PCHenry.ExploreLatLong.GPSPosition ),
  Description = "GPSPosition Debugger Visualizer" )]
namespace PCHenry.Debugger.Visualizer
{
  class GPSPositionVisualizer : Microsoft.VisualStudio.DebuggerVisualizers.DialogDebuggerVisualizer
  {
    protected override void Show( Microsoft.VisualStudio.DebuggerVisualizers.IDialogVisualizerService windowService,
      Microsoft.VisualStudio.DebuggerVisualizers.IVisualizerObjectProvider objectProvider )
    {
      GPSPosition gpsLocation = (GPSPosition)objectProvider.GetObject();

      GPSPositionForm frm = new GPSPositionForm( gpsLocation );
      frm.ShowDialog();
    }
  }
}

Notice the assembly attribute at the top right?  This is what helps Visual Studio figure out when to use THIS visualizer for debugging.  The first parameter is yourself (this class), next is the VisualizerObjectSource and is common everytime you'll use this, next is the target type of object you're using this visualizer/Windows Form to display "lipstick" for, and lastly the english (or your own language of choice) for the magnifying class to display for selecting this visualizer (this is the text displayed above by the number 3 arrow).

The next thing is the override the Show method.  Use the IDialogVisualizerService parameter to give you the ShowDialog() method and the IVisualizerObjectProvider parameter to give you the actual object (GPSPosition in this case) to debug into.  As I hope you can see, IVisualizerObjectProvider is an object and therefore requires casting.  The more observant coder (SG?) might comment about using "as", so here goes an "alternative ending." (it is Halloween afterall and alternative endings seem to be common on horror movies)

    protected override void Show( IDialogVisualizerService windowService, IVisualizerObjectProvider objectProvider )
    {
      GPSPositionForm frm;

      //GPSPosition gpsLocation = (GPSPosition)objectProvider.GetObject();
      GPSPosition gpsLocation = objectProvider.GetObject() as GPSPosition;

      if( gpsLocation != null )
      {
        frm = new GPSPositionForm( gpsLocation );
      }
      else
      {
        frm = new GPSPositionForm( new GPSPosition( 0, 0, "Unable to determine GPS latitude or longitude", "NA" ) );
      }

      windowService.ShowDialog( frm );
    }

Ok, at this point, we can compile our code and create the DLL.  Beautiful!  But now we need to deploy this so Visual Studio can use it.  To deploy this, you'll need to copy the DLL to the C:\Program Files (x86)\Microsoft Visual Studio 9.0\Common7\Packages\Debugger\Visualizers directory.  Notice the (x86) in the directory structure?  If you're using x86 Windows, just ignore that part, the rest is the same.  If you copy this over correctly, you'll see something similar to this.

Deploying to Visualizers directory

 At this point, you're ready to test this out.  Set a break point in your first application on the first line AFTER you run the SelectedIndexChanged event.  Right mouse click the locationToShow variable and select the magnifying glass to run your Visualizer or the down arrow to select from the options (if there are multiple Visualizers).

If you get an error that looks like this, then obviously something's gone wrong with the code, DOH!  HHMMM a bug with the debugger code?  Yup, ironic isn't it?  Or is that recursive?  ANYWAYS, just dig into it and you'll eventually figure it out.  HINT, WATCH OUT FOR DB CALLS!  Don't forget, you're in something like a static class state, and you don't necessarily have everything you need or want.  If you want DB access, you'll probably have to carry an application.config around (and keep it up to date too!).  So be careful.

Runtime error with Debugger Visualizer

If you're thinking to yourself..........are we done yet?  If you're ok with manually copying the DLLs over to the Visualizers directory, then ya, you're done!  Enjoy!  If not, then read on for just a short bit.  Visual Studio has a small ability to run script-like code after builds/compiles.  Let's try to use this capability to get VS to copy over our DLL instead of us doing it all the time.

Goto the Visualizers Class Library's Project Preferences and select the Build Events tab on the left hand side.

Visualizers Build Events

In the Post-build event, I would suggest adding this line.  This is the MS-DOS xcopy command to copy the deliverables (namely your custom Visualizer DLL) to the Visualizers directory (don't forget to change the (x86) from this path if you're not using a 64-bit machine).  Make sure you select the bottom listbox correctly for your preference.

xcopy "$(SolutionDir)$(ProjectName)\$(OutDir)$(TargetFileName)" "C:\Program Files (x86)\Microsoft Visual Studio 9.0\Common7\Packages\Debugger\Visualizers" /y

If you're asking what are the $(text) strings above?  Those are macros and I would HIGHLY suggest using them to help minimize the "it works on my machine, I don't have any clue why it's not working on yours?"  As you can see from the above first few macros, it doesn't matter where my coworkers/friend's/YOU compile this, I'm pretty confident this piece will work on your machine because of it (except for the (x86) part that is).

Something to watch out for when using Post-build events, if for some reason, ANY reason, VS cannot run those build events, chances are high you'll see the problems manifest themselves as Errors in your builds.  The description will tell you where the error was, but it won't be anything linked to your code, nor will it be very helpful (VS can only report back what the command line functions report back).  So!  For example, IF you didn't heed my warnings above and start VS with Administrative Privileges, you will be finding out riiiiiiiiiiiiiiiiiiiiiight about now that you're getting errors when you try to xcopy the files over to the Visualizers directory because you don't have permissions and xcopy isn't going to ask you for permissions, it'll just fail.  So if you're in this boat, restart VS but this time, start with Admin privs please?!

Well, there you have it.  Your own way to customize debugging your own classes!  Now you can put a happy face on all your custom classes and show them off for all their glory.  Now it's time to grab a coffee and get coding!

 

NOTE: Unfortunately there hasn't been too many 2008 focused exampes of creating these visualizers, but thankfully, the same stuff you did with 05 works with 08!  Cool!  The crux now is not necessarily the IDE but the OS!  Yup, the OS, Windows!  Back with VS 05, UAC wasn't around and causing people troubles.  This time around it is and although you can get away without running VS with Administrator privileges, it makes your life a bit easier.  Why?  Cause part of "installing" or deploying your Debugger Visualizer is to copy the DLL files to a Program Files sub folder and if you run VS normally you won't be able to use VS to do that automagically (we're going to use VS to automate this step for us).

Resources:

Source Code: http://www.pchenry.com:8080/svn/blog/trunk/2009/DebuggingVisualizer

MSDN: Visual Studio Debugger Visualizers

MSDN: Creating a Debugger Visualizer Using Visual Studio 2005 Beta 2

MSDN: DebuggerVisualizerAttribute Class

The Code Project: Authoring Visual Studio Debugger Visualizers

CODE: Creating Debugger Visualizers with Visual Studio 2005

Alex Pinsker: Comprehensive list of Debugger Visualizers for Visual Studio

Google Maps: Google Map Parameters

QueryStringParameters: Google Maps Query String Parameters

Microsoft Technet: Xcopy

Tags:
Categories:
Location: Blogs Parent Separator TechTidBits

10 comment(s) so far...


Re: Visual Studio Debugger Visualizers are VERY cool! You gotta check this out!

Thanks Jason, I'm honoured! Jason Haley - Interesting Finds: October 29, 2009, COOL!
http://jasonhaley.com/blog/post/2009/10/28/Interesting-Finds-October-29-2009.aspx

PS If you're reading this, check out Jason's blog, if you're time crunched, check out his daily blog for quick'n'interesting links on a variety of different topics! I've been following his link for years (no joke! it's that cool!).

By phenry on   Thursday, October 29, 2009 12:36 PM

Re: Visual Studio Debugger Visualizers are VERY cool! You gotta check this out!

Man visualizers old news.

By Um on   Thursday, October 29, 2009 1:44 PM

Re: Visual Studio Debugger Visualizers are VERY cool! You gotta check this out!

Hi Um, thank you for the comment.

Maybe old news, but as the saying goes "Oldie but a goodie!" :> haha The other reason is to serve as a personal reminder how to do this when I forget how in a few months/years (or weeks haha). The macros piece is something I added which isn't in other blogs about the same topic, as well the screen cap of the runtime error is something I haven't seen in other blogs neither.

By phenry on   Thursday, October 29, 2009 1:47 PM

Re: Visual Studio Debugger Visualizers are VERY cool! You gotta check this out!

Perhaps it's old news to many, but new news to me. Keep up the good work Pete!

By SBoucher on   Saturday, October 31, 2009 12:53 PM

Re: Visual Studio Debugger Visualizers are VERY cool! You gotta check this out!

Thanks SBoucher, much appreciated. Always something new to learn and something to share (information or a kind "keep up the great work!"). Happy Halloween all!

By phenry on   Saturday, October 31, 2009 12:54 PM

Re: Visual Studio Debugger Visualizers are VERY cool! You gotta check this out!

This is excellent. In my previous job, I had to deal with video streams and lot of times I had to debug issues with static pictures present in stream. The way I used to deal with it was to save the byte array into a jpg or bmp and later view the image via some image viewer to verify the results. This technique could had been very handly if I knew it at that time. Thanks for your good work Peter.

By Kamran on   Sunday, November 08, 2009 1:55 PM

Re: Visual Studio Debugger Visualizers are VERY cool! You gotta check this out!

Very cool, well, not that you had to do it the brute force way in the past, but that you can use this way now for anything that comes up in the future. My boss built one of these for green screen scrapping (mainframe emulation) and it was very cool! Like you say, a lot better than looking at a byte array!

Thanks for leaving a comment Kamran! Have a good one!

By phenry on   Sunday, November 08, 2009 1:59 PM

Re: Visual Studio Debugger Visualizers are VERY cool! You gotta check this out!

Hey Kamran, I used your idea of saving the image in my new Image Debugger Visualizer I just created. Seems only natural, if you're looking at a cool image, you just might want to save it for later use? Since you're already debugging it, why not give the developer the option if it's not that hard to do. Thanks for the idea.

http://www.pchenry.com/Home/tabid/36/EntryID/200/Default.aspx

By phenry on   Thursday, November 19, 2009 9:59 PM

Very Nice Demo, Thanks!

Chanced on this site today. Thanks for showing this information! Very Nice

By John Peters on   Wednesday, November 24, 2010 1:05 PM

Re: Visual Studio Debugger Visualizers are VERY cool! You gotta check this out!

Glad I could help John! Very cool! That's the 2nd reason for posting! 1st reason? To finger-flick my brain when I forgot how to do this stuff and google it and then am surprised SOMEONE blogged about it, then even more surprise I'M the one that blogged about it! hahaha

Thanks again John, have a great day!

By phenry on   Wednesday, November 24, 2010 1:43 PM

Your name:
Gravatar Preview
Your email:
(Optional) Email used only to show Gravatar.
Your website:
Title:
Comment:
Add Comment   Cancel 
     
  
Copyright 1999-2012 by PCHenry.com   Terms Of Use  Privacy Statement