This posting is part of a series detailing how to write a custom Debugger Visualizer for Visual Studio.
Posts in the series:
- Writing A (ReadOnly) Custom Debugger Visualizer for Visual Studio
- Writing A Custom Debugger Visualizer for Non-Serializable Types or More Complex Objects
- Writing A Custom Debugger Visualizer using WPF for the UI
- Modifying The Live Object in Your Custom Debugger Visualizer for Visual Studio
- Installation, Limitations, and Security Considerations for Your Custom Debugger Visualizer for Visual Studio
I've also given a talk on this topic: Putting the Visual into the Visual Studio Debugger.
You can find code samples to go along with this series in my
DebugVisualizer GitHub repository.
Loading Visualizers (and Where To Install)
Visualizers registered in assemblies currently loaded into the application will be available. That is, the
DebuggerVisualizer attribute must have been loaded and the assembly housing the visualizer must be loaded (otherwise you'll get an error message from Visual Studio saying it couldn't find the assembly).
If the visualizers are included in projects in the currently loaded solution, typically everything "just works". However, if the visualizers are in a seperate assembly (not part of the current solution) which you reference, you may need to force the assembly to be loaded. If you use the actual type in the
DebuggerVisualizer attribute (ex:
[DebuggerVisualizer(typeof(SomeTypeVisualizer))]), that should be enough. But if you use the string-based constructor for the attribute (ex:
[DebuggerVisualizer("MyVisualizers.SomeTypeVisualizer")]), you may need to force the assembly to be loaded. One way to do that is add a static constructor to your main class that references a type from the visualizer assembly, like this:
//force loading of the visualizer assembly and Microsoft.VisualStudio.DebuggerVisualizers
var foo = typeof(VisualizerExamples.DebuggerVisualizer.Exception.SimpleExceptionVisualizer);
This, however, makes it pretty difficult to include standalone visualizers in NuGet packages. (Though, including visualizers in the assembly with the types they visualize would work via NuGet)
The more common approach is to install the assembly with your visualizers into one of two places:
<VisualStudioInstallPath>\Common7\Packages\Debugger\Visualizers\to make them available to all users on the computer.
My Documents\<VisualStudioVersion>\Visualizers\to make them available to the current user.
Note: The visualizers must be installed on the machine running the application being debugged, so if you're using a remote debugging session, they must be installed on the remote machine as well as your local machine.
You can find a number of visualizers in the Visual Studio Marketplace, and they'll install into one of these locations.
Keep in mind that parts of the Debugger Visualizer effectively run with the security level of Visual Studio, and all too many of us developers run Visual Studio as Administrator (thanks, in large part, to the crazy that is IIS's security model). So that means the visualizer you select could happily go off and delete your entire hard drive, send all of your source code to an FTP site, or whatever Hollywood-style hacker-in-a-hoodie nefarious stuff you can imagine.
So make sure you know and trust the source for any visualizers you choose to run. And since visualizers can been shipped with libraries you're using, they may be available without you having directly installed anything.
Visual Studio already has some safeguards in place, such as disallowing app-side
VisualizerObjectSource object running in partial-trust. But, in my experience, very few of us make use of anything but full-trust environments. So Don't Be Stupid and pay a little extra attention to which visualizers you see vs. what you expect to see listed.
Supported Types and Limitations
Generics have very poor support. You can only register a visualizer with an open generic type (ex:
Dictionary<,>) but not a constructed type (ex:
Dictionary<int, string>). But in the visualizer, you only get an
object, so without a lot of crazy reflection, you have no way of knowing the types used in the generic placeholders.
Universal Windows Platform (UWP) apps and Windows "Store" apps do not support custom visualizers, though they can use the built-in string visualizers (Text, HTML, XML, JSON).
The visualizers described in this post only work for managed code. Native VisualCpp assemblies won't use them.
Visual Studio for Mac uses the Mono Soft-Mode debugger, which does not use the same visualizers as Visual Studio for Windows.
Make sure to take a look at the other posts in my Debugger Visualizer series.