Compartir a través de


Alias de función del modelo de datos del depurador

Los alias de función son un nombre corto único por el que un usuario del depurador puede acceder a la funcionalidad definida en una extensión del depurador (ya sea escrito en C++ o en algún entorno de scripting como JavaScript). Este nombre corto se asocia a un objeto de función del modelo de datos (un objeto que implementa IModelMethod). Esa función toma un número arbitrario de argumentos y devuelve un único valor. El efecto de invocar un alias de función y lo que se hace con ese valor depende de cómo se invoca el alias de función y del depurador de host en el que se invoca.

En este tema se supone que el lector está familiarizado con el modelo de objetos del depurador y JavaScript. Para obtener información sobre el uso de objetos de depurador con JavaScript, vea Objetos de depurador nativo en extensiones de JavaScript.

Algunos de los ejemplos que se muestran aquí usan el comando dx, para obtener más información sobre cómo trabajar con el comando dx, vea dx (Display Debugger Object Model Expression). Además, se usa LINQ, que se describe en Uso de LINQ con los objetos del depurador.

Uso del alias de función como comandos de extensión

Todos los alias de función creados en WinDbg se pueden invocar como si fueran extensiones de depuración ! comandos "bang". Si la función no toma ningún argumento, simplemente invocar !aliasName hará que se llame a la función y se muestre el valor de resultado. Como ejemplo (creado con extensibilidad de JavaScript)

Por ejemplo, esta función proporciona dos valores constantes, pi y e.

function __constants()
{
    return { math_constants : { pi :  3.1415926535 , e :  2.7182818284}, description : "Archimedes' pi and Euler's number e" };
}

function initializeScript()
{
    return [new host.functionAlias(__constants, "constants")];
}

Aquí se muestran los resultados de llamar al alias de función.

0:000> !constants
@$constants()                 : [object Object]
    math_constants   : [object Object]
    description      : Archimedes' pi and Euler's number e

Los vínculos DML a objetos complejos se generarán automáticamente. Al hacer clic en el math_constants mostrado anteriormente, se producirá la siguiente salida.

0:000> dx -r1 @$constants().math_constants
@$constants().math_constants                 : [object Object]
    pi               : 3.141593
    e                : 2.718282

Si la función tiene argumentos, se pueden proporcionar después del propio comando del alias de función. Tenga en cuenta que lo que ocurra después del comando alias de función se considera una expresión y se evalúa como tal. La cadena de texto no se pasa directamente a la función . Para una expresión de argumento único, puede venir después del propio comando del alias de función. Para varios argumentos, se deben paréntesis como si fuera una llamada de función como se muestra en este ejemplo siguiente.

function __oneArgument(x)
{
    return -x;
}

function __twoArguments(x, y)
{
    return x + y;
}

function initializeScript()
{
    return [new host.functionAlias(__oneArgument, "neg"),
            new host.functionAlias(__twoArguments, "add")];
}

Estas dos funciones se pueden llamar como se muestra aquí.

0:000> !neg 42
@$neg(42)        : -42

0:000> !add (5, 7)
@$add(5, 7)      : 0xc

Uso del alias de función con el evaluador de expresiones dx

Además de la extensión de depuración ! sintaxis de comandos "bang" para invocar una función con alias, todos los nombres asociados a alias de función están disponibles directamente en el evaluador de expresiones dx cuando @$ como se muestra aquí.

0:000> dx @$neg(42)
@$neg(42)        : -42

0:000> dx @$add(99, 77)
@$add(99, 77)    : 0xb0

Consideraciones sobre el diseño del alias de función

Un alias de función nunca debe ser la única manera en que se expone la funcionalidad en la gran mayoría de las extensiones del modelo de datos. Una extensión de modelo de datos (ya sea en C++ o JavaScript) casi siempre debe incluir los datos que expone asociados a un tipo u otro concepto del depurador. Las cosas asociadas a los procesos deben estar en Debugger.Models.Process o en un subespacio de nombres de ese objeto. Un alias de función puede ser una manera cómoda de obtener (o transformar) datos que podrían requerir una consulta significativamente más larga.

Como ejemplo de modo kernel, la consulta siguiente toma el árbol de dispositivos PnP y la aplana en una lista plana simple de dispositivos:

0: kd> dx @$cursession.Devices.DeviceTree.Flatten(n => n.Children),5
@$cursession.Devices.DeviceTree.Flatten(n => n.Children),5                
    [0x0]            : HTREE\ROOT\0
    [0x1]            : ROOT\volmgr\0000 (volmgr)
    [0x2]            : ROOT\BasicDisplay\0000 (BasicDisplay)
    [0x3]            : ROOT\CompositeBus\0000 (CompositeBus)
    [0x4]            : ROOT\vdrvroot\0000 (vdrvroot)
    [...]     

Este código de JavaScript muestra cómo se puede implementar como alias de función.

function __flatDevices()
{
    return host.currentSession.Devices.DeviceTree.Flatten(n => n.Children);
}

function initializeScript()
{
    return [new host.functionAlias(__flatDevices, "devices")];
}

A continuación, el alias de función se puede invocar como un comando de extensión de depuración.

0: kd> !devices
@$devices()                
    [0x0]            : HTREE\ROOT\0
    [0x1]            : ROOT\volmgr\0000 (volmgr)
    [0x2]            : ROOT\BasicDisplay\0000 (BasicDisplay)
    [0x3]            : ROOT\CompositeBus\0000 (CompositeBus)
    [0x4]            : ROOT\vdrvroot\0000 (vdrvroot)
    [0x5]            : ROOT\spaceport\0000 (spaceport)

    ...

Una de las ventajas con el uso de un alias de función es que se puede refinar aún más mediante la sintaxis dx. En este ejemplo, se agrega una cláusula where para buscar nodos de dispositivo que contengan "Harddisk".

0: kd> dx @$devices().Where(n => n.InstancePath.Contains("Harddisk"))
@$devices().Where(n => n.InstancePath.Contains("Harddisk"))                
    [0x0]            : STORAGE\VolumeSnapshot\HarddiskVolumeSnapshot1
    [0x1]            : STORAGE\VolumeSnapshot\HarddiskVolumeSnapshot2
    [0x2]            : STORAGE\VolumeSnapshot\HarddiskVolumeSnapshot3
    [0x3]            : STORAGE\VolumeSnapshot\HarddiskVolumeSnapshot4
    [0x4]            : STORAGE\VolumeSnapshot\HarddiskVolumeSnapshot5
    [0x5]            : STORAGE\VolumeSnapshot\HarddiskVolumeSnapshot6

Los comandos LINQ, como los siguientes, se pueden usar con alias funcionales: . Todo. Cualquier. Contar. Primero. Aplanar. GroupBy, . Último. OrderBy, . OrderByDescending, . Seleccione y . Dónde. Estos métodos siguen (lo más cerca posible) el formulario del método LINQ de C#. Para obtener más información, vea Using LINQ With the debugger objects.

de visualización de cuadrícula

Al igual que con otros comandos dx, puede hacer clic con el botón derecho en un comando después de ejecutarlo y hacer clic en "Mostrar como cuadrícula" o agregar "-g" al comando para obtener una vista de cuadrícula de los resultados. A continuación, puede hacer clic en cualquier columna para ordenar, por ejemplo, en InstancePath.

0: kd> dx -g @$devices().OrderBy(obj => obj.@"InstancePath")

Captura de pantalla de la salida de cuadrícula de alias de función de objetos de depurador con filas ordenadas.

Ejemplo de subprocesos de proceso

Los objetos del depurador se proyectan en un espacio de nombres raíz en "Debugger". Los procesos, módulos, subprocesos, pilas, marcos de pila y variables locales están disponibles para usarse en una consulta LINQ.

En este ejemplo javaScript se muestra cómo mostrar el recuento de subprocesos para los procesos de sesiones actuales:

function __Processes()
{
    return host.currentSession.Processes.Select(p => ({Name: p.Name, ThreadCount: p.Threads.Count()}));
}

function initializeScript()
{
    return [new host.functionAlias(__Processes, "Processes")];
}

Esto muestra la salida de ejemplo con ! Alias de función de procesos.

0: kd> !Processes
@$Processes()                
    [0x0]            : [object Object]
    [0x4]            : [object Object]
    [0x1b4]          : [object Object]
    [0x248]          : [object Object]
    [0x2c4]          : [object Object]
    [0x340]          : [object Object]
    [0x350]          : [object Object]
    [0x3d4]          : [object Object]
    [0x3e8]          : [object Object]
    [0x4c]           : [object Object]
    [0x214]          : [object Object]
    [0x41c]          : [object Object]
    [0x494]          : [object Object]

...    

En este ejemplo se muestran los cinco primeros procesos con el número de subprocesos más grande.

0: kd> dx -r1 @$Processes().OrderByDescending(p =>p.ThreadCount),5
@$Processes().OrderByDescending(p =>p.ThreadCount),5                
    [0x4]            : [object Object]
    [0x180]          : [object Object]
    [0x978]          : [object Object]
    [0xda4]          : [object Object]
    [0x3e8]          : [object Object]
    [...]   

Consulte también

dx (expresión del modelo de objetos display debugger)

usar LINQ con los objetos del depurador

objetos de depurador nativo en NatVis

objetos de depurador nativo en extensiones de JavaScript