Notatka
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Aliasy funkcji to unikatowa krótka nazwa, za pomocą której użytkownik debugera może uzyskać dostęp do funkcji zdefiniowanych w rozszerzeniu debugera (niezależnie od tego, czy jest napisany w języku C++, czy w środowisku skryptowym, takim jak JavaScript). Ta krótka nazwa jest skojarzona z obiektem funkcji modelu danych (obiekt, który implementuje element IModelMethod). Ta funkcja przyjmuje dowolną liczbę argumentów i zwraca pojedynczą wartość. Wpływ wywoływania aliasu funkcji i tego, co robi się z tej wartości, zależy od sposobu wywoływania aliasu funkcji i wywoływania debugera hosta w obrębie.
W tym temacie założono, że czytelnik jest zaznajomiony z modelem obiektów debugera i językiem JavaScript. Aby uzyskać informacje o korzystaniu z obiektów debugera w języku JavaScript, zobacz Native Debugger Objects in JavaScript Extensions (Rozszerzenia JavaScript).
Niektóre z przedstawionych tutaj przykładów używają polecenia dx, aby uzyskać więcej informacji na temat pracy z poleceniem dx, zobacz dx (Display Debugger Object Model Expression). Ponadto używany jest linQ, który jest opisany w Using LINQ With the debugger objects.
Używanie aliasu funkcji jako poleceń rozszerzenia
Wszystkie aliasy funkcji utworzone w usłudze WinDbg można wywołać tak, jakby były one rozszerzeniem debugowania ! polecenia "bang". Jeśli funkcja nie przyjmuje żadnych argumentów, po prostu wywołanie !aliasName spowoduje wywołanie funkcji i wyświetlenie wartości wyniku. Jako przykład (utworzony za pomocą rozszerzalności języka JavaScript)
Na przykład ta funkcja udostępnia dwie stałe wartości, pi i 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")];
}
Wyniki wywoływania aliasu funkcji są wyświetlane tutaj.
0:000> !constants
@$constants() : [object Object]
math_constants : [object Object]
description : Archimedes' pi and Euler's number e
Linki DML do złożonych obiektów będą generowane automatycznie. Kliknięcie powyższego math_constants spowoduje wyświetlenie następujących danych wyjściowych.
0:000> dx -r1 @$constants().math_constants
@$constants().math_constants : [object Object]
pi : 3.141593
e : 2.718282
Jeśli funkcja ma argumenty, można je podać po samym poleceniu aliasu funkcji. Należy pamiętać, że wszystko, co następuje po poleceniu aliasu funkcji, jest traktowane jako wyrażenie i jest oceniane jako takie. Ciąg tekstowy nie jest przekazywany bezpośrednio do funkcji. W przypadku pojedynczego wyrażenia argumentu może on pochodzić po samym poleceniu aliasu funkcji. W przypadku wielu argumentów powinny one być nawiasem tak, jakby było to wywołanie funkcji, jak pokazano w następnym przykładzie.
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")];
}
Te dwie funkcje można wywołać, jak pokazano tutaj.
0:000> !neg 42
@$neg(42) : -42
0:000> !add (5, 7)
@$add(5, 7) : 0xc
Alias funkcji jest używany z ewaluatorem wyrażeń dx
Oprócz rozszerzenia debugowania ! składnia polecenia "bang" na potrzeby wywoływania funkcji aliasu, wszystkie nazwy skojarzone z aliasami funkcji są dostępne bezpośrednio w ewaluatorze wyrażeń dx, gdy prefiksowany przez @$, jak pokazano tutaj.
0:000> dx @$neg(42)
@$neg(42) : -42
0:000> dx @$add(99, 77)
@$add(99, 77) : 0xb0
Zagadnienia dotyczące projektowania aliasu funkcji
Alias funkcji nigdy nie powinien być jedynym sposobem uwidocznienia funkcji w zdecydowanej większości rozszerzeń modelu danych. Rozszerzenie modelu danych (czy w języku C++ lub JavaScript) powinno zawierać niemal zawsze dane, które są ujawniane z typem lub inną koncepcją debugera. Elementy skojarzone z procesami powinny znajdować się w obszarze Debugger.Models.Process lub podrzędnej przestrzeni nazw tego obiektu. Alias funkcji może być wygodnym sposobem uzyskiwania (lub przekształcania) danych, które mogą wymagać znacznie dłuższego zapytania.
Na przykład w trybie jądra następujące zapytanie pobiera drzewo urządzeń PnP i spłaszcza je w prostą płaską listę urządzeń:
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)
[...]
Ten kod JavaScript pokazuje, jak można to zaimplementować jako alias funkcji.
function __flatDevices()
{
return host.currentSession.Devices.DeviceTree.Flatten(n => n.Children);
}
function initializeScript()
{
return [new host.functionAlias(__flatDevices, "devices")];
}
Alias funkcji można następnie wywołać jako polecenie rozszerzenia debugowania.
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)
...
Jedną z zalet korzystania z aliasu funkcji jest to, że można go dodatkowo udoskonalić przy użyciu składni dx. W tym przykładzie dodano klauzulę where, aby wyszukać węzły urządzeń zawierające ciąg "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
Polecenia LINQ, takie jak poniższe, mogą być używane z aliasami funkcjonalnymi — . Cały. Jakikolwiek. Hrabia. Pierwszy. Spłaszczyć. GroupBy, . Ostatni. OrderBy, . OrderByDescending, . Wybierz i . Gdzie. Te metody są zgodne (jak najbliżej) formularza metody LINQ języka C#. Aby uzyskać więcej informacji, zobacz Using LINQ With the debugger objects.
wyświetlania siatki
Podobnie jak w przypadku innych poleceń dx, możesz kliknąć prawym przyciskiem myszy polecenie po jego wykonaniu i kliknąć polecenie "Wyświetl jako siatkę" lub dodać "-g" do polecenia, aby uzyskać widok siatki wyników. Następnie możesz kliknąć dowolną kolumnę do sortowania, na przykład na instancePath.
0: kd> dx -g @$devices().OrderBy(obj => obj.@"InstancePath")
Przykład wątków przetwarzania
Obiekty debugera są projektowane w przestrzeni nazw rooted w "Debugger". Procesy, moduły, wątki, stosy, ramki stosu i zmienne lokalne są dostępne do użycia w zapytaniu LINQ.
W tym przykładzie w języku JavaScript pokazano, jak wyświetlić liczbę wątków dla bieżących procesów sesji:
function __Processes()
{
return host.currentSession.Processes.Select(p => ({Name: p.Name, ThreadCount: p.Threads.Count()}));
}
function initializeScript()
{
return [new host.functionAlias(__Processes, "Processes")];
}
Spowoduje to wyświetlenie przykładowych danych wyjściowych za pomocą polecenia ! Przetwarza alias funkcji.
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]
...
W tym przykładzie jest wyświetlanych 5 pierwszych procesów z największą liczbą wątków.
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]
[...]
Zobacz też
dx (Display Debugger Object Model Expression)
używanie LINQ z obiektami debugera
obiektów natywnego debugera w natVis
natywnych obiektów debugera w rozszerzeniach Języka JavaScript