为C++编写图形化的调试可视化工具(Writing graphical debugger visualizers for C++)

转载自:https://code.msdn.microsoft.com/Writing-graphical-debugger-a17e3d75


Writing graphical debugger visualizers for C++

Visual Studio 2012 introduces support for graphical debugger visualizer plugins for native types. This sample project shows how to create such a visualizer for std::vector<int> objects.

Introduction

Visual Studio 2012 introduces support for graphical debugger visualizer plugins for native types. These visualizers allow developers to view a variable or an object in a custom user interface that is appropriate for the data type. They complement the existing visualizers that have been used in Visual Studio debugger (e.g. built-in text, HTML, XML visualizers and the visualizers for .NET objects).

This sample project demonstrates how to create a simple native visualizer for std::vector<int> objects. The visualizer is packaged in a VSIX that can be easily deployed to a user’s machine. 

Building the Sample

You need to have Visual Studio 2012 SDK in order to open and build the project in this sample. You can download it fromhttp://www.microsoft.com/en-us/download/details.aspx?id=30668.

Description

The following sections briefly explain the steps involved in creating a graphical debugger visualizer:

1.      Create a VSPackage to host the visualizer service

The visualizer code must be contained in a package which will be loaded by the debugger when needed. You can create your visualizer project based on the “Visual Studio Package” template to help with this. Note that you can implement this VSPackage in different programming languages (this sample uses C#). You can just pick the language of your choice in Visual Studio Package Wizard when you are creating the project.

2.      Declare the service to be consumed by the debugger

The created package must proffer a service to be consumed by the debugger. The relevant code that defines the service in the sample is in VectorVisualizerPackage.cs and shown below. The important point to note below is the GUID for the IVectorVisualizerService which will be used in the next step.

C#
/// <summary> 
/// Vector visualizer service exposed by the package 
/// </summary> 
[Guid("5452AFEA-3DF6-46BB-9177-C0B08F318025")] 
public interface IVectorVisualizerService { } 
 
[PackageRegistration(UseManagedResourcesOnly = true)] 
[ProvideService(typeof(IVectorVisualizerService), ServiceName = "VectorVisualizerService")] 
[InstalledProductRegistration("Vector Visualizer Sample""Vector Visualizer Sample""1.0")] 
[Guid("C37A4CFC-670F-454A-B40E-AC08578ABABD")] 
public sealed class VectorVisualizerPackage : Package 
{ 
    /// <summary> 
    /// Initialization of the package; register vector visualizer service 
    /// </summary> 
    protected override void Initialize() 
    { 
        base.Initialize(); 
 
        IServiceContainer serviceContainer = (IServiceContainer)this; 
 
        if (serviceContainer != null) 
        { 
            serviceContainer.AddService(typeof(IVectorVisualizerService), new VectorVisualizerService(), true); 
        } 
    } 
} 
3.      Define the visualizer and its applicable types in the natvis file

In order to register the visualizer with the debugger and to declare the types it can handle, a natvis file must be used (please seehttp://code.msdn.microsoft.com/Writing-type-visualizers-2eae77a2 for more information on natvis files). The debugger reads the entries in this file to match types viewed in the debugger with the registered visualizers. The following shows the natvis file used by the sample. Note that the guid of the service declared in the previous step is used here:

XML
<?xml version="1.0" encoding="utf-8"?> 
<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010"  <UIVisualizer ServiceId="{5452AFEA-3DF6-46BB-9177-C0B08F318025}" Id="1" MenuName="Vector Visualizer"/> 
 
  <Type Name="std::vector&lt;int,*&gt;"    <UIVisualizer ServiceId="{5452AFEA-3DF6-46BB-9177-C0B08F318025}" Id="1" /> 
  </Type> 
</AutoVisualizer> 

UIVisualizer is identified by a ServiceId - Id pair. ServiceId is the GUID of the service exposed by the visualizer package, Id is a unique identifier that can be used to differentiate visualizers if a service provides more than one visualizer. MenuNameattribute is what the users see as the name of the visualizer when they open the dropdown next to the magnifying glass icon in a debugger variable window.

Each type defined in the natvis file must explicitly list the visualizers that can display them. The debugger reads the visualizer references in the type entries to match types with the registered visualizers.

For VSIX deployment, a NativeVisualizer asset needs to be added to the project. This file should also be included in the extension manifest and the VSIX (i.e. set 'Build Action' to 'Content' and 'Include in VSIX' attribute to true). The following shows the related section in source.extension.vsixmanifest:

XML
<?xml version="1.0" encoding="utf-8"?> 
<PackageManifest Version="2.0.0" xmlns="http://schemas.microsoft.com/developer/vsx-schema/2011" xmlns:d="http://schemas.microsoft.com/developer/vsx-schema-design/2011"  . 
  . 
  . 
  <Assets    <Asset Type="NativeVisualizer" Path="VectorVisualizer.xml"/> 
    <Asset Type="Microsoft.VisualStudio.VsPackage" d:Source="Project" d:ProjectName="%CurrentProject%" Path="|%CurrentProject%;PkgdefProjectOutputGroup|" /> 
  </Assets> 
</PackageManifest> 

4.      Implement the visualizer service

The service object exposed by the package must implement IVsCppDebugUIVisualizer interface (defined in Microsoft.VisualStudio.Debugger.Interop.11.0) which will be called by the debugger when the user requests visualization on an object. This interface has one DisplayValue method that is implemented in VectorVisualizerService.cs:

C#
/// <summary> 
/// Plots the given vector contents in a modal window 
/// </summary> 
/// <param name="ownerHwnd">Parent window hwnd</param> 
/// <param name="visualizerId">The visualizer id to use</param> 
/// <param name="debugProperty">DebugProperty for a vector object</param> 
/// <returns>An HRESULT</returns> 
public int DisplayValue(uint ownerHwnd, uint visualizerId, IDebugProperty3 debugProperty) 

The method is passed an IDebugProperty3 reference which represents the variable being visualized in the debugger variable windows.  Using this interface you can get the property values, enumerate children properties shown in the debugger windows to help visualize the variable. For instance, the sample visualizer uses IDebugProperty3 methods to get the values of _Myfirst and _Mylast fields of the vector type. After that it uses IDebugMemoryContext2, IDebugMemoryBytes2 interface methods to read the debuggee memory pointed to by the _Myfirst field that contains the elements in the vector. Lastly, it display the values read using a chart control.

5.      Test the visualizer

After you’ve built the project, you can test it in the experimental instance of Visual Studio. Using the simple code snippet below, put a breakpoint on the return statement, and start debugging in the experimental instance. Launch the visualizer on myVector variable, and

C++
void main() 
{ 
    std::vector<int> myVector; 
 
    for (int i = 0; i < 100; i++) 
    { 
        myVector.push_back( ((i - 50) * (i - 50))); 
    } 
 
    return; 
} 

you should see the following chart that plots the values contained in the myVector variable:



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值