Skip to content

Cpp Custom Visualizer Sample

Gregg Miskelly edited this page Jan 13, 2020 · 14 revisions

This repo contains a sample C/C++ Custom Visualizer. The sample changes how FILETIME variables are formatted so that instead of showing up as a pair of unsigned 32-bit values they instead show up as a date and time.

Screenshot:

Watch Window Screenshot

What is a Custom Visualizer?

The Visual Studio C/C++ Expression Evaluator allows customization of the display of variables in the debugger based on the type of that variable (example: change the way CExampleClass variables are displayed) using .natvis files. Natvis files add rules to format a type either declaratively or by running custom code in the debugger. This custom code is called a Custom Visualizer. Most of the time it is easier and much less error prone to use the declarative approach. But Custom Visualizers are useful when formatting a type is too complicated to be done declaratively.

Natvis documentation can be found on docs.microsoft.com.

Running the Sample in Visual Studio

To run the sample in Visual Studio, open CppCustomVisualizer.sln from the CppCustomVisualizer directory. Then do the following:

  1. In Solution Explorer, right click on the 'vsix' project and use 'Set As StartUp Project'.
  2. Using the solution/platform configurations drop down menu from the toolbar, make sure that the solution configuration is 'Debug' and the platform is 'x86' (IMPORTANT will not work if the platform is 'x64', which is the default).
  3. If you using Visual Studio 2019 and you want to debug the extension, install the Microsoft Child Process Debugging Power Tool.
  4. Hit F5 to launch an experimental instance of Visual Studio under the debugger. NOTE: This project pulls in some NuGet packages so Visual Studio will need to be able to download packages during build. If downloading packages fails, make sure 'Allow NuGet to download missing packages during build.' from Tools -> Options -> NuGet Package Manager, is checked.
  5. In the Experimental Instance:
    • The experimental instance should load the 'TargetApp' project
    • Hit F5 to build and run 'TargetApp' under the debugger
    • The debugger should stop at the __debugbreak(); line
    • Evaluate creationTime in the watch window. If everything worked correctly, you should see creationTime visualized as a date time rather than two raw 32-bit unsigned integers.

If hitting F5 on the vsix project doesn't cause an experimental instance of VS to start, see troubleshooting instructions below.

Browsing the CppCustomVisualizer project

The CppCustomVisualizer directory contains three subdirectories with source code -- dll, vsix and TargetApp. Let's look at 'dll' first since this has the most important files.

Dll directory files

The 'dll' directory contains the Concord extension

File Description
_EntryPoint.cpp/.h The one and only public (exported) class in the sample. In Concord, classes implement interfaces, and Concord calls into these classes through the implemented interfaces. Custom visualizers implement the IDkmCustomVisualizer interface. So _EntryPoint.cpp contains the implementation of this interface, which is the only interesting source code in this sample.
CppCustomVisualizer.natvis The C++ Expression Evaluator (EE) uses .natvis files to control how types are formatted. For types formatted with a Custom Visualizer, the only important thing is declare the 'VisualizerId' to indicate which visualizer to use.
CppCustomVisualizer.vsdconfigxml CppCustomVisualizer.vsdconfigxml is an XML file which describes the sample component – what classes does it have, which interfaces does each class implement, when should these interfaces be called. The sample’s build process runs a custom tool over this file (vsdconfigtool.exe) which validates this file and turns it into a binary file (CppCustomVisualizer.vsdconfig) which is deployed alongside CppCustomVisualizer.dll. For a custom visualizer, the important thing is to indicate that IDkmCustomVisualizer is implemented with a particular VisualizerId.
packages.config, packages.version.props This project obtains Concord headers, libs and build tools from nuget.org. These two files indicate the version to obtain.

VSIX Directory

The 'vsix' directory contains a project file used to package the sample into a .vsix file so that it can be installed into Visual Studio. The Installing Extensions page has more information about how Visual Studio extensions are installed.

File Description
source.extension.vsixmanifest Declares metadata about the extension, such as its name, company, and version.
VSIXSourceItems.props This declares the set of files to be included in the .vsix file for this extension. One important thing to note is that in order to support Visual Studio 2019, this extension needs to provide both an x86-compiled dll and an x64-compiled dll because, as of VS 2019, custom visualizers are usually, but not always loaded in an x64 process. Because of this we declare the dll as a vsix item explicitly rather than using project-to-project references.
Build-x64.targets As mentioned in the previous item, this extension needs to compile the dll project for both x86 and x64 as part of building the extension. This file contains custom MSBuild targets to do just that. NOTE: make sure that your vsix project is configured to NOT build for x64 through Solution Build Manager or else this will cause an infinite set of builds.

TargetApp Directory

The 'TargetApp' directory contains just an example project that uses FILETIME that we will debug to show the sample in action.

Troubleshooting

If Debug Launch doesn't start Visual Studio correctly

When you 'F5' from your primary Visual Studio instance on the vsix project, it should start up a second 'experimental' instance of Visual Studio, and this experimental instance should load the 'TargetApp' project. If this isn't happening for you, a few troubleshooting steps:

  1. Make sure that your startup project is the vsix project, and the solution/platform is Debug/x86.
  2. Right click on the vsix project in solution explorer and bring up project properties. Then switch to the 'Debugging' tab, and make sure that the settings are correct:
    • 'Debugger to launch' is Local Windows Debugger
    • 'Command' is $(DevEnvDir)devenv.exe
    • 'Command Arguments' is /rootsuffix Exp $(SolutionDir)\TargetApp\TargetApp.sln
    • 'Working Directory' is $(ProjectDir)

If your debugging project settings are different then somehow the project system must have decided to ignore the defaults set in 'vsix.vcxproj'. You could try to force the project system to go back to the defaults by closing your solution, deleting ConcordExtensibilitySamples\CppCustomVisualizer\vsix\vsix.vcxproj.user and then reopening the solution. You could also just correct these settings by hand by pasting in these values into project properties.

Clone this wiki locally