c++ - net - visual studio configuration manager
¿Cómo escribir una DLL de visualizador nativa personalizada para el depurador de Visual Studio 2012? (2)
Aquí está el código de C ++ que comprende la DLL AddIn. Llamé al archivo NatvisAddIn.cpp y el proyecto creó 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;
}
Aquí está el archivo .natvis que el depurador de Visual Studio 2012 usa para mostrar el valor. Colóquelo en un archivo .natvis. Lo llamé NatvisAddIn.natvis. El archivo indica al depurador de VS 2012 que llame a NatvisAddIn.dll. El dll contiene dos llamadas al método visualizador; MyClassFormatter para formatear MyClass y MyStructFormatter para formatear MyStruct. El depurador mostrará el valor formateado del método en la pantalla Auto, Watch o Tooltip para cada instancia del tipo especificado (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>
Coloque el archivo NatvisAddIn.dll compilado y los archivos NatvisAddIn.natvis en una de las siguientes tres ubicaciones:
%VSINSTALLDIR%/Common7/Packages/Debugger/Visualizers (requires admin access)
%USERPROFILE%/My Documents/Visual Studio 2012/Visualizers/
VS extension folders
Deberá asegurarse de que existe la siguiente clave de registro y el valor es 1:
[HKEY_CURRENT_USER / Software / Microsoft / VisualStudio / 11.0_Config / Debugger]
"EnableNatvisDiagnostics" = dword: 00000001
Si todo va bien, verás que los mensajes natvis aparecen en la ventana de salida del depurador de Visual Studio. Los mensajes mostrarán si Natvis fue capaz de analizar los archivos .natvis. Los resultados de analizar cada archivo .natvis se muestran en la ventana de resultados. Si algo está mal, use el comando "dumpbin / exports" para verificar que los nombres de los métodos DLL coincidan exactamente con el tipo de archivo .navis =. Asegúrese también de que los archivos .dll y .natvis actuales se hayan copiado en el directorio apropiado.
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.
Programa de prueba:
#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;
}
Recursos de información:
/ Xml / Schemas / natvis.xsd
code.msdn.microsoft.com/windowsdesktop/…
http://blogs.msdn.com/b/vcblog/archive/2012/07/12/10329460.aspx
¿Qué se necesita para escribir una DLL de visualizador nativa personalizada en C ++ para Visual Studio 2012 depurador? Quiero mostrar un valor que solo se puede calcular a partir de una clase / estructura bajo demanda, por lo tanto, se requiere una DLL del visualizador nativo. Visual Studio 2012 usa un nuevo método para implementar visualizadores nativos llamado Natvis. A partir de este momento, hay muy poca información correcta sobre Natvis y especialmente sobre el uso de Natvis para llamar a un visualizador DLL. La DLL calculará una cadena de visualización basada en los valores de los miembros de clase / estructura.
Para la depuración de la versión de 64 bits, se deben usar las siguientes líneas:
auto realAddress = pHelper->GetRealAddress(pHelper);
pHelper->ReadDebuggeeMemoryEx(pHelper, realAddress, sizeof(MyClass), &c, &nGot );
Para el ejemplo anterior, la versión de 64 bits podría verse así:
#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;
}