在C中为Visual Studio 2012调试器编写自定义本机可视化DLL需要什么?我想显示一个只能根据需要从类/结构计算的值,因此需要一个本机可视化DLL . Visual Studio 2012使用一种新方法来实现名为Natvis的本机可视化工具 . 截至目前,关于Natvis的信息非常少,尤其是使用Natvis调用可视化DLL . DLL将根据类/结构成员值计算显示字符串 .
这是包含AddIn DLL的C代码 . 我将文件命名为NatvisAddIn.cpp,该项目创建了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; }
以下是Visual Studio 2012调试器用于显示值的.natvis文件 . 将其放在.natvis文件中 . 我把它命名为NatvisAddIn.natvis . 该文件指示VS 2012调试器调用NatvisAddIn.dll . 该DLL包含两个可视化方法调用; MyClassFormatter格式化MyClass和MyStructFormatter以格式化MyStruct . 调试器将在Auto,Watch或工具提示显示中为指定类型的每个实例(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>
将已编译的NatvisAddIn.dll文件和NatvisAddIn.natvis文件放入以下三个位置之一:
%VSINSTALLDIR%\Common7\Packages\Debugger\Visualizers (requires admin access) %USERPROFILE%\My Documents\Visual Studio 2012\Visualizers\ VS extension folders
您需要确保存在以下注册表项且值为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: 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.
测试程序:
#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; }
信息资源:
\ 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
对于64位版本调试,应使用以下行:
auto realAddress = pHelper->GetRealAddress(pHelper); pHelper->ReadDebuggeeMemoryEx(pHelper, realAddress, sizeof(MyClass), &c, &nGot );
对于前面的示例,64位版本可能如下所示:
#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 ); class MyClass { public: int publicInt; }; ADDIN_API HRESULT MyClassFormatter( DWORD dwAddress, DEBUGHELPER *pHelper, int nBase, BOOL bUniStrings, char *pResult, size_t max, DWORD reserved ) { MyClass c; DWORD nGot; auto realAddress = pHelper->GetRealAddress(pHelper); pHelper->ReadDebuggeeMemoryEx(pHelper, realAddress, sizeof(MyClass), &c, &nGot ); sprintf_s(pResult,max,"Dll MyClass: max=%d nGot=%d MyClass=%llx publicInt=%d",max, nGot, realAddress, c.publicInt); return S_OK; }
2 回答
这是包含AddIn DLL的C代码 . 我将文件命名为NatvisAddIn.cpp,该项目创建了NatvisAddIn.dll .
以下是Visual Studio 2012调试器用于显示值的.natvis文件 . 将其放在.natvis文件中 . 我把它命名为NatvisAddIn.natvis . 该文件指示VS 2012调试器调用NatvisAddIn.dll . 该DLL包含两个可视化方法调用; MyClassFormatter格式化MyClass和MyStructFormatter以格式化MyStruct . 调试器将在Auto,Watch或工具提示显示中为指定类型的每个实例(MyClass,MyStruct)显示方法的格式化值 .
将已编译的NatvisAddIn.dll文件和NatvisAddIn.natvis文件放入以下三个位置之一:
您需要确保存在以下注册表项且值为1:
如果一切顺利,您将看到natvis消息出现在Visual Studio的调试器输出窗口中 . 这些消息将显示Natvis是否能够解析.natvis文件 . 解析每个.natvis文件的结果显示在输出窗口中 . 如果出现问题,请使用命令“dumpbin / exports”仔细检查DLL方法的名称是否与.navis文件的Type =完全匹配 . 还要确保已将当前的.dll和.natvis文件复制到相应的目录中 .
测试程序:
信息资源:
对于64位版本调试,应使用以下行:
对于前面的示例,64位版本可能如下所示: