如何编写Visual Studio 2012调试器的自定义本机可视化DLL? [英] How to write a custom native visualizer DLL for Visual Studio 2012 debugger?

查看:261
本文介绍了如何编写Visual Studio 2012调试器的自定义本机可视化DLL?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为Visual Studio 2012调试器在C ++中编写自定义本机可视化DLL需要什么?我想显示一个只能从一个类/结构按需求计算的值,因此需要一个本地可视化DLL。 Visual Studio 2012使用一种新方法来实现本地可视化程序Natvis。到目前为止,在Natvis上很少有正确的信息,尤其是使用Natvis调用可视化DLL。该DLL将基于类/ struct成员值计算显示字符串。

解决方案

这里是包含AddIn DLL的C ++代码。我命名文件NatvisAddIn.cpp和项目创建NatvisAddIn.dll。

  #includestdafx.h
#include< iostream>
#include< windows.h>

#define ADDIN_API __declspec(dllexport)

typedef struct tagDEBUGHELPER
{
DWORD dwVersion;
HRESULT(WINAPI * ReadDebuggeeMemory)(struct tagDEBUGHELPER * pThis,DWORD dwAddr,DWORD nWant,VOID * pWhere,DWORD * nGot);
//从这里只有当dwVersion> = 0x20000
DWORDLONG(WINAPI * GetRealAddress)(struct tagDEBUGHELPER * pThis);
HRESULT(WINAPI * ReadDebuggeeMemoryEx)(struct tagDEBUGHELPER * pThis,DWORDLONG qwAd​​dr,DWORD nWant,VOID * pWhere,DWORD * nGot);
int(WINAPI * GetProcessorType)(struct tagDEBUGHELPER * pThis);
} DEBUGHELPER;

typedef HRESULT(WINAPI * CUSTOMVIEWER)(DWORD dwAddress,DEBUGHELPER * phelper,int nBase,BOOL bUniStrings,char * pResult,size_t max,DWORD reserved);

externCADDIN_API HRESULT MyClassFormatter(DWORD dwAddress,DEBUGHELPER * pHelper,int nBase,BOOL bUniStrings,char * pResult,size_t max,DWORD reserved);
externCADDIN_API HRESULT MyStructFormatter(DWORD dwAddress,DEBUGHELPER * pHelper,int nBase,BOOL bUniStrings,char * pResult,size_t max,DWORD reserved);

class MyClass
{
public:
int publicInt;
};

struct MyStruct {int i; };

ADDIN_API HRESULT MyClassFormatter(DWORD dwAddress,DEBUGHELPER * pHelper,int nBase,BOOL bUniStrings,char * pResult,size_t max,DWORD reserved)
{
MyClass c;
DWORD nGot;
pHelper-> ReadDebuggeeMemory(pHelper,dwAddress,sizeof(MyClass),& c,& nGot);
sprintf_s(pResult,max,Dll MyClass:max =%d nGot =%d MyClass =%x publicInt =%d,max,nGot,dwAddress,c.publicInt);
return S_OK;
}

ADDIN_API HRESULT MyStructFormatter(DWORD dwAddress,DEBUGHELPER * pHelper,int nBase,BOOL bUniStrings,char * pResult,size_t max,DWORD reserved)
{
MyStruct s;
DWORD nGot;
pHelper-> ReadDebuggeeMemory(pHelper,dwAddress,sizeof(MyStruct),& s,& nGot);
sprintf_s(pResult,max,Dll MyStruct:max =%d nGot =%d MyStruct =%x i =%d,max,nGot,dwAddress,s.i);
return S_OK;
}

这是Visual Studio 2012调试器用来显示值的.natvis文件。将其放在.natvis文件中。我命名为NatvisAddIn.natvis。该文件指示VS 2012调试器调用NatvisAddIn.dll。 dll包含两个可视化方法调用; MyClassFormatter格式化MyClass,MyStructFormatter格式化MyStruct。调试器将在Auto,Watch或工具提示显示中为指定类型的每个实例(MyClass,MyStruct)显示方法的格式化值。

 <?xml version =1.0encoding =utf-8?> 
< AutoVisualizer xmlns =http://schemas.microsoft.com/vstudio/debugger/natvis/2010>
< Type Name =MyClass>
< DisplayString LegacyAddin =NatvisAddIn.dllExport =MyClassFormatter>< / DisplayString>
< / Type>
< Type Name =MyStruct>
< DisplayString LegacyAddin =NatvisAddIn.dllExport =MyStructFormatter>< / DisplayString>
< / Type>
< / AutoVisualizer>

将编译的NatvisAddIn.dll文件和NatvisAddIn.natvis文件放入以下三个位置:

 %VSINSTALLDIR%\Common7\Packages\Debugger\Visualizers(需要管理员存取)

%USERPROFILE%\ My Documents \Visual Studio 2012\Visualizers \

与扩展文件夹

您需要确保以下注册表项存在,值为1:


HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\11.0_Config\Debugger]



EnableNatvisDiagnostics= DWORD:00000001


如果一切正常,您将看到natvis消息出现在Visual Studio的调试器输出窗口中。消息将显示Natvis是否能够解析.natvis文件。解析每个.natvis文件的结果显示在输出窗口中。如果有问题,使用命令dumpbin / exports来检查DLL方法的名称是否与.navis文件的Type =完全匹配。还要确保当前的.dll和.natvis文件已被复制到相应的目录。

  Natvis:解析natvis xml文件: C:\Program Files(x86)\Microsoft Visual Studio 11.0 \Common7 \Packages\Debugger\Visualizers \atlmfc.natvis。 
Natvis:完成解析XML natvis文件:C:\Program文件(x86)\Microsoft的Visual Studio 11.0\Common7\Packages\Debugger\Visualizers\atlmfc.natvis。
Natvis:解析XML natvis文件:C:\Program文件(x86)\Microsoft的Visual Studio 11.0\Common7\Packages\Debugger\Visualizers\concurrency.natvis。
Natvis:完成解析XML natvis文件:C:\Program文件(x86)\Microsoft的Visual Studio 11.0\Common7\Packages\Debugger\Visualizers\concurrency.natvis。
Natvis:解析XML natvis文件:C:\Program文件(x86)\Microsoft的Visual Studio 11.0\Common7\Packages\Debugger\Visualizers\NatvisAddIn.natvis。
Natvis:完成解析XML natvis文件:C:\Program文件(x86)\Microsoft的Visual Studio 11.0\Common7\Packages\Debugger\Visualizers\NatvisAddIn.natvis。
Natvis:解析XML natvis文件:C:\Program文件(x86)\Microsoft的Visual Studio 11.0\Common7\Packages\Debugger\Visualizers\stl.natvis。
Natvis:完成解析XML natvis文件:C:\Program文件(x86)\Microsoft的Visual Studio 11.0\Common7\Packages\Debugger\Visualizers\stl.natvis。
Natvis:解析natvis xml文件:C:\Program Files(x86)\Microsoft Visual Studio 11.0 \Common7\Packages\Debugger\Visualizers\windows.natvis。
Natvis:完成解析natvis xml文件:C:\Program Files(x86)\Microsoft Visual Studio 11.0 \Common7\Packages\Debugger\Visualizers\windows.natvis。
Natvis:解析natvis xml文件:C:\Program Files(x86)\Microsoft Visual Studio 11.0 \Common7 \Packages\Debugger\Visualizers \winrt.natvis。
Natvis:完成解析natvis xml文件:C:\Program Files(x86)\Microsoft Visual Studio 11.0 \Common7\Packages\Debugger\Visualizers\winrt.natvis。

测试程序:

  #includestdafx.h
#include< iostream>

class MyClass
{
public:
int publicInt;
};

struct MyStruct {int i; };

int _tmain(int argc,_TCHAR * argv [])
{
struct MyStruct s = {1234};
std :: cout<< s.i < std :: endl;
MyClass * c = new MyClass;
c-> publicInt = 1234;
std :: cout<< c-> publicInt<< std :: endl;
return 0;
}

信息资源:



< blockquote>

\Xml\Schemas\\\
atvis.xsd



http://code.msdn.microsoft.com/windowsdesktop/Writing-type-visualizers-2eae77a2



< p> do-with-them.aspx> http://blogs.msdn.com/b/mgoldin/archive/2012/06/06/visual-studio-2012-and-debugger-natvis-files-what-c​​an-i -do-with-them.aspx



http://blogs.msdn.com/b/vcblog/archive/2012/07/12/10329460.aspx



What is needed to write a custom native visualizer DLL in C++ for Visual Studio 2012 debugger? I want to display a value that can only be calculated from a class/struct on-demand hence a native visualizer DLL is required. Visual Studio 2012 uses a new method for implementing native visualizers called Natvis. As of this time, there is very little correct information on Natvis and especially on using Natvis to call a visualizer DLL. The DLL will calculate a display string based on class/struct member values.

解决方案

Here's the C++ code that comprises the AddIn DLL. I named the file NatvisAddIn.cpp and the project created NatvisAddIn.dll.

#include "stdafx.h"
#include <iostream>
#include <windows.h>

#define ADDIN_API __declspec(dllexport)

typedef struct tagDEBUGHELPER
{
    DWORD dwVersion;
    HRESULT (WINAPI *ReadDebuggeeMemory)( struct tagDEBUGHELPER *pThis, DWORD dwAddr, DWORD nWant, VOID* pWhere, DWORD *nGot );
    // from here only when dwVersion >= 0x20000
    DWORDLONG (WINAPI *GetRealAddress)( struct tagDEBUGHELPER *pThis );
    HRESULT (WINAPI *ReadDebuggeeMemoryEx)( struct tagDEBUGHELPER *pThis, DWORDLONG qwAddr, DWORD nWant, VOID* pWhere, DWORD *nGot );
    int (WINAPI *GetProcessorType)( struct tagDEBUGHELPER *pThis );
} DEBUGHELPER;

typedef HRESULT (WINAPI *CUSTOMVIEWER)( DWORD dwAddress, DEBUGHELPER *pHelper, int nBase, BOOL bUniStrings, char *pResult, size_t max, DWORD reserved );

extern "C" ADDIN_API HRESULT MyClassFormatter( DWORD dwAddress, DEBUGHELPER *pHelper, int nBase, BOOL bUniStrings, char *pResult, size_t max, DWORD reserved );
extern "C" ADDIN_API HRESULT MyStructFormatter( DWORD dwAddress, DEBUGHELPER *pHelper, int nBase, BOOL bUniStrings, char *pResult, size_t max, DWORD reserved );

class MyClass
{
public:
    int publicInt;
};

struct MyStruct { int i; };

ADDIN_API HRESULT MyClassFormatter( DWORD dwAddress, DEBUGHELPER *pHelper, int nBase, BOOL bUniStrings, char *pResult, size_t max, DWORD reserved )
{
    MyClass c;
    DWORD nGot;
    pHelper->ReadDebuggeeMemory(pHelper,dwAddress,sizeof(MyClass),&c,&nGot);
    sprintf_s(pResult,max,"Dll MyClass: max=%d nGot=%d MyClass=%x publicInt=%d",max,nGot,dwAddress,c.publicInt);
    return S_OK;
}

ADDIN_API HRESULT MyStructFormatter( DWORD dwAddress, DEBUGHELPER *pHelper, int nBase, BOOL bUniStrings, char *pResult, size_t max, DWORD reserved )
{
    MyStruct s;
    DWORD nGot;
    pHelper->ReadDebuggeeMemory(pHelper,dwAddress,sizeof(MyStruct),&s,&nGot);
    sprintf_s(pResult,max,"Dll MyStruct: max=%d nGot=%d MyStruct=%x i=%d",max,nGot,dwAddress,s.i);
    return S_OK;
}

Here is the .natvis file which Visual Studio 2012 debugger uses to display the value. Place it in a .natvis file. I named it NatvisAddIn.natvis. The file instructs VS 2012 debugger to call NatvisAddIn.dll. The dll contains two visualizer method calls; MyClassFormatter to format MyClass and MyStructFormatter to format MyStruct. The debugger will show the method's formatted value in the Auto, Watch or tooltip display for each instance of the specified type (MyClass, MyStruct).

<?xml version="1.0" encoding="utf-8"?>
    <AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
    <Type Name="MyClass">
        <DisplayString LegacyAddin="NatvisAddIn.dll" Export="MyClassFormatter"></DisplayString>
    </Type>
    <Type Name="MyStruct">
        <DisplayString LegacyAddin="NatvisAddIn.dll" Export="MyStructFormatter"></DisplayString>
    </Type>
</AutoVisualizer>

Place both the compiled NatvisAddIn.dll file and the NatvisAddIn.natvis files into one of the following three locations:

%VSINSTALLDIR%\Common7\Packages\Debugger\Visualizers (requires admin access)

%USERPROFILE%\My Documents\Visual Studio 2012\Visualizers\

VS extension folders

You will need to make sure the following registry key exists and the value is 1:

[HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\11.0_Config\Debugger]

"EnableNatvisDiagnostics"=dword:00000001

If all goes well, you will see natvis messages appear in Visual Studio's debugger Output window. The messages will show whether Natvis was able to parse the .natvis files. Results of parsing every .natvis file is shown in the output window. If something is wrong, use the command "dumpbin/exports " to double check that the DLL methods' names are exactly matching the .navis file's Type=. Also make sure the current .dll and .natvis files have been copied to the appropriate directory.

Natvis: Parsing natvis xml file: C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\Packages\Debugger\Visualizers\atlmfc.natvis.
Natvis: Done parsing natvis xml file: C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\Packages\Debugger\Visualizers\atlmfc.natvis.
Natvis: Parsing natvis xml file: C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\Packages\Debugger\Visualizers\concurrency.natvis.
Natvis: Done parsing natvis xml file: C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\Packages\Debugger\Visualizers\concurrency.natvis.
Natvis: Parsing natvis xml file: C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\Packages\Debugger\Visualizers\NatvisAddIn.natvis.
Natvis: Done parsing natvis xml file: C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\Packages\Debugger\Visualizers\NatvisAddIn.natvis.
Natvis: Parsing natvis xml file: C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\Packages\Debugger\Visualizers\stl.natvis.
Natvis: Done parsing natvis xml file: C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\Packages\Debugger\Visualizers\stl.natvis.
Natvis: Parsing natvis xml file: C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\Packages\Debugger\Visualizers\windows.natvis.
Natvis: Done parsing natvis xml file: C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\Packages\Debugger\Visualizers\windows.natvis.
Natvis: Parsing natvis xml file: C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\Packages\Debugger\Visualizers\winrt.natvis.
Natvis: Done parsing natvis xml file: C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\Packages\Debugger\Visualizers\winrt.natvis.

Test program:

#include "stdafx.h"
#include <iostream>

class MyClass
{
public:
    int publicInt;
};

struct MyStruct { int i; };

int _tmain(int argc, _TCHAR* argv[])
{
    struct MyStruct s = {1234};
    std::cout << s.i << std::endl;
    MyClass *c = new MyClass;
    c->publicInt = 1234;
    std::cout << c->publicInt << std::endl;
    return 0;
}

Information resources:

\Xml\Schemas\natvis.xsd

http://code.msdn.microsoft.com/windowsdesktop/Writing-type-visualizers-2eae77a2

http://blogs.msdn.com/b/mgoldin/archive/2012/06/06/visual-studio-2012-and-debugger-natvis-files-what-can-i-do-with-them.aspx

http://blogs.msdn.com/b/vcblog/archive/2012/07/12/10329460.aspx

这篇关于如何编写Visual Studio 2012调试器的自定义本机可视化DLL?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆