Ejemplo EEAddIn: complemento del evaluador de expresiones de depuración
Actualización: noviembre 2007
El ejemplo EEAddin muestra la forma de ampliar el evaluador de expresiones nativo del depurador mediante la API del complemento Evaluador de expresiones.
Nota de seguridad: |
---|
Este código de ejemplo se proporciona para ilustrar un concepto y no debe utilizarse en aplicaciones o sitios Web, ya que quizás no ilustre las prácticas de codificación más seguras. Microsoft no asume ninguna responsabilidad por daños incidentales o consecuentes en caso de que el código de ejemplo se utilice para propósitos distintos de aquellos para los que se concibió. |
Para obtener ejemplos e instrucciones para su instalación:
En el menú Ayuda de Visual Studio, haga clic en Ejemplos.
Para obtener más información, vea Localizar archivos de ejemplo.
La lista de ejemplos completa con la versión más reciente está disponible en línea en la página Visual Studio 2008 Samples.
También encontrará ejemplos en el disco duro de su equipo. De manera predeterminada, los ejemplos y el archivo Léame se copian en una carpeta bajo \Archivos de programa\Visual Studio 9.0\Samples\. Para las versiones Express de Visual Studio, todos los ejemplos están en línea.
API del complemento Evaluador de expresiones
El evaluador de expresiones forma parte del depurador que interpreta (evalúa) expresiones. Cuando establezca un punto de interrupción en una expresión o escriba una expresión en una ventana de depuración, el evaluador de expresiones interpretará el resultado. Para obtener información detallada, vea Expresiones en el depurador. Con la API del complemento Evaluador de expresiones puede ampliar el evaluador de expresiones para controlar tipos nuevos.
Si desea ampliar el evaluador de expresiones para un tipo nuevo, debe escribir una función como parte de un archivo DLL de Win32 (en el mismo directorio que autoexp.dat) y exportarla por nombre. También tiene que agregar una línea al archivo autoexp.dat. Puede ampliar el evaluador de expresiones para más de un tipo exportando varias funciones del archivo DLL.
Generar y ejecutar el ejemplo
Los pasos necesarios para generar y ejecutar este ejemplo se dividen en tres partes:
Para generar y ejecutar este ejemplo
Genere un archivo DLL del complemento evaluador de expresiones (eeaddin.dll).
Edite autoexp.dat para utilizar el archivo DLL del complemento evaluador de expresiones.
Pruebe el complemento; para ello, cree un proyecto que utilice el tipo de datos personalizado evaluado por autoexp.dat.
Los siguientes procedimientos describen estos métodos con detalle.
Para generar el archivo DLL del complemento evaluador de expresiones
En Visual Studio, abra la solución eeaddin.sln.
En el menú Generar, haga clic en Generar.
Copie el archivo eeaddin.dll resultante al directorio common7\ide (el mismo directorio que contiene devenv.exe).
En el menú Archivo, haga clic en Cerrar solución.
Para editar autoexp.dat
En el menú Archivo, seleccione Abrir y haga clic en Archivo.
En el cuadro de diálogo Abrir archivo, busque el archivo autoexp.dat (en el directorio common7\packages\debugger) y haga clic en Abrir.
Edite autoexp.dat para agregar las líneas siguientes:
_SYSTEMTIME=$ADDIN(eeaddin.dll,AddIn_SystemTime@28) _FILETIME=$ADDIN(eeaddin.dll,AddIn_FileTime@28)
Guarde autoexp.dat.
Para crear un proyecto que utilice los tipos de datos personalizados
En el menú Archivo, seleccione New y haga clic en Proyecto.
En el cuadro de diálogo Nuevo proyecto, resalte Proyectos de Visual C++, haga clic en Aplicación MFC, escriba un nombre para el proyecto y haga clic en Aceptar.
En el Asistente para aplicaciones MFC, haga clic en Finalizar. El proyecto debe ser una aplicación MFC, ya que en el paso siguiente agregará funciones MFC.
En la aplicación MFC, agregue un objeto SYSTEMTIME o FILETIME.
SYSTEMTIME *s = new SYSTEMTIME(); FILETIME *f = new FILETIME(); GetSystemTime(s); SystemTimeToFileTime(s,f);
En el menú Generar, haga clic en Generar.
Inicie la depuración y examine los objetos SYSTEMTIME o FILETIME en la ventana de inspección.
Cómo funciona el ejemplo
Si desea ampliar el evaluador de expresiones para un tipo de datos personalizado, debe escribir una función de visor personalizada en el archivo DLL del complemento evaluador de expresiones. La función utiliza un puntero a un objeto en el espacio de memoria del programa que se está depurando (no en el espacio de memoria del evaluador de expresiones que está ampliando). No puede utilizar conversiones normales con este puntero. Debe leer el puntero y los datos a los que apunta para utilizar una función de devolución de llamada. Un puntero de devolución de llamada del tipo DEBUGHELPER* apunta a un objeto con varios métodos.
La sintaxis tiene el siguiente aspecto:
HRESULT WINAPI CustomViewer(
DWORD dwAddress, // low 32-bits of address
DEBUGHELPER *pHelper, // callback pointer to access helper functions
int nBase, // decimal or hex
BOOL bIgnore, // not used
char *pResult, // where the result needs to go
size_t max, // how large the above buffer is
DWORD dwReserved // always pass zero
)
El ejemplo tiene dos implementaciones de este tipo de función, AddIn_SystemTime y AddIn_FileTime en timeaddin.cpp. La estructura DEBUGHELPER (definida en custview.h) consta de punteros de función que le ayudan a escribir la extensión. Este puntero se pasa a la función CustomViewer y puede utilizarlo para llamar a las funciones auxiliares.
Puede obtener el tipo de procesador con pHelper->GetProcessorType. Existen dos métodos para leer la memoria, pHelper->ReadDebuggeeMemory y pHelper->ReadDebuggeeMemoryEx. ReadDebuggeeMemoryEx controla direcciones de 64 bits y lo admite el depurador de Visual Studio .NET. ReadDebuggeeMemory no controla direcciones de 64 bits y lo admiten los depuradores de Visual Studio .NET y Visual C++ 6.0. Si el complemento sólo está diseñado para el depurador de Visual Studio .NET, puede utilizar ReadDebuggeeMemoryEx. Si el complemento también tiene que funcionar con Visual C++ 6.0, debe comprobar el campo dwVersion y evitar llamar a ReadDebuggeeMemoryEx para Visual C++ 6.0.
El siguiente fragmento de código funciona con los dos depuradores y lee el contenido de un objeto local, localobject (que tiene el tipo MyType), del programa que se está depurando:
DWORDLONG qwRealAddress;
DWORD dwGot;
MyType localobject;
if (pHelper->dwVersion<0x20000)
{
// Visual C++ 6.0 version
qwRealAddress = dwAddress;
pHelper->ReadDebuggeeMemory( pHelper, dwAddress,
sizeof(localobject), &localobject, &dwGot );
}
else
{
qwRealAddress = pHelper->GetRealAddress(pHelper);
pHelper->ReadDebuggeeMemoryEx( pHelper, qwRealAddress,
sizeof(localobject), &localobject, &dwGot );
}
// TODO: display localobject here
Editar autoexp.dat
En la sección [AutoExpand] de autoexp.dat, las líneas que agregue tendrán la siguiente sintaxis:
type=$ADDIN(dllname.dll,exportname)
Por ejemplo:
_SYSTEMTIME=$ADDIN(eeaddin.dll,AddIn_SystemTime)
O bien
_FILETIME=$ADDIN(eeaddin.dll,AddIn_FileTime)
Si el archivo DLL no está en el directorio que contiene devenv.exe o no está en la ruta (PATH), debe utilizar el nombre completo del archivo DLL, con la ruta. El argumento exportname distingue entre mayúsculas y minúsculas y debe coincidir exactamente con el nombre exportado que recibió al ejecutar dumpbin –exports en el archivo DLL.
Para probar el depurador con el nuevo complemento, detenga primero la depuración del programa que estuviera depurando al instalar el nuevo archivo DLL y, a continuación, inicie una nueva sesión de depurador.
Nota El complemento se ejecuta en el depurador; por tanto, si el código provoca un bloqueo, se bloqueará el IDE.