Condividi tramite


Uso di LINQ Con gli oggetti debugger

La sintassi LINQ può essere usata con gli oggetti debugger per cercare e modificare i dati. L'uso della sintassi LINQ con il comando dx consente un'esperienza più coerente rispetto all'uso dei comandi del debugger. L'output e le opzioni sono coerenti indipendentemente dall'oggetto debugger che si sta esaminando. Le query LINQ consentono di porre domande come "Quali sono i primi 5 processi che eseguono la maggior parte dei thread?".

Gli oggetti debugger vengono proiettati in uno spazio dei nomi rooted in "Debugger". Processi, moduli, thread, stack, stack frame e variabili locali sono tutti disponibili per l'uso in una query LINQ.

LINQ è concettualmente simile al Structured Query Language (SQL) usato per eseguire query sui database. È possibile usare diversi metodi LINQ per cercare, filtrare e analizzare i dati di debug. Viene usata la sintassi del metodo LINQ C#. Per altre informazioni sulla sintassi LINQ e LINQ C#, vedere Introduzione con LINQ in C#

LINQ usato nel supporto del debugger usa la "sintassi del metodo" di LINQ e non la "sintassi di query". Per altre informazioni sulle differenze, vedere LINQ (Language-Integrated Query).

I comandi LINQ, ad esempio i seguenti, possono essere usati con gli oggetti debugger. Tutti. Qualsiasi. Conteggio. Prima. Appiattire. Groupby. Ultima. Orderby. Orderbydescending. Selezionare e . Dove. Questi metodi seguono (il più possibile) il modulo del metodo LINQ C#.

Oggetti debugger nativi

Gli oggetti debugger nativi rappresentano vari costrutti e comportamenti dell'ambiente del debugger. Gli oggetti debugger di esempio includono quanto segue.

  • sessione
  • Thread/Thread
  • Processi/Processo
  • Stack Frame/Stack Frame
  • Variabili locali
  • Moduli/Modulo
  • Utilità
  • State
  • Impostazioni

È anche possibile usare gli oggetti debugger con NatVis. Per altre informazioni, vedere Oggetti debugger nativi in NatVis. Per informazioni sull'uso di oggetti debugger con JavaScript, vedere Oggetti debugger nativi nelle estensioni JavaScript. Per informazioni sull'uso di C++ e degli oggetti driver, vedere Cenni preliminari sul modello di dati del debugger C++.

Comando Dx

Gli esempi illustrati qui usano il comando dx, per altre informazioni sull'uso del comando dx, vedere dx (Display Debugger Object Model Expression).

Sviluppo di una query LINQ

Un modo per sviluppare una query dell'oggetto debugger LINQ consiste nell'usare i collegamenti DML visualizzati per esplorare il modello di dati per individuare prima l'oggetto debugger che verrà usato nella query.

Per questo esempio, si vuole visualizzare un elenco di processi in una sessione di debug del kernel e il numero di thread per ognuno di questi processi.

Per avviare l'esplorazione, è possibile usare il comando dx per visualizzare l'oggetto debugger di primo livello.

0: kd> dx Debugger
Debugger
    Sessions
    Settings
    State
    Utility

Dopo aver selezionato gli argomenti di primo livello, si determina che Sessioni ha un aspetto più interessante, quindi si seleziona il collegamento DML per visualizzare che contiene Processi.

0: kd> dx -r1 Debugger.Sessions[0]
Debugger.Sessions[0]                 : Remote KD: KdSrv:Server=@{<Local>},Trans=@{NET:Port=50005,Key=MyKey}
    Processes
    Id               : 0
    Attributes

Selezionare quindi più avanti per esaminare il processo specifico e si noterà che i thread associati a tale processo sono disponibili. Quando si seleziona Thread per uno dei processi, vengono visualizzati tutti i thread associati a tale processo.

0: kd> dx -r1 Debugger.Sessions[0].Processes[1428].Threads
Debugger.Sessions[0].Processes[1428].Threads
    [0x598]          : <Unable to get stack trace> [Switch To]
    [0x1220]         : <Unable to get stack trace> [Switch To]
    [0x6f8]          : nt!KiSwapContext+0x76 (fffff806`4466a186)  [Switch To]
    [0x128c]         : <Unable to get stack trace> [Switch To]
    [0x27e4]         : nt!KiSwapContext+0x76 (fffff806`4466a186)  [Switch To] 

Ora sappiamo che i dati che è necessario visualizzare il numero di thread associati a un processo sono disponibili nel modello a oggetti del debugger.

Per rendere più breve la query LINQ, è possibile usare le variabili definite dal sistema descritte più avanti in questo argomento per visualizzare i processi associati alla sessione corrente.

0: kd> dx @$cursession.Processes
@$cursession.Processes                
    [0x0]            : Idle [Switch To]
    [0x4]            : System [Switch To]
    [0x90]           : Registry [Switch To]
...

Aggiungere quindi un'istruzione select. Per iniziare, è possibile specificare il campo Nome.

0: kd> dx @$cursession.Processes.Select(p => p.Name)
@$cursession.Processes.Select(p => p.Name)                
    [0x0]            : Idle
    [0x4]            : System
    [0x90]           : Registry
...

Per lo scenario è necessario anche il numero di thread. Poiché sono presenti due campi, creare un tipo anonimo usando una nuova sintassi di tipo anonimo, simile alla sintassi di tipo anonimo di C#descritta di seguito in Variabili definite dall'utente.

dx @$cursession.Processes.Select(p => new {Name = p.Name, Threads = p.Threads})

Con questo comando 'dx' non stampa più il nome, quindi aggiungere -r2 (due livelli) per visualizzare Nome e Thread.

dx -r2 @$cursession.Processes.Select(p => new {Name = p.Name, Threads = p.Threads})
@$cursession.Processes.Select(p => new {Name = p.Name, Threads = p.Threads})                
    [0x0]           
        Name             : Idle
        Threads         
    [0x4]           
        Name             : System
        Threads         
    [0x90]          
        Name             : Registry
        Threads       

A questo punto viene visualizzato il nome del processo e un elenco di thread. Per visualizzare ThreadCount, usare . Metodo Count().

0: kd> dx -r2 @$cursession.Processes.Select(p => new {Name = p.Name, ThreadCount = p.Threads.Count()})
@$cursession.Processes.Select(p => new {Name = p.Name, ThreadCount = p.Threads.Count()})                
    [0x0]           
        Name             : Idle
        ThreadCount      : 0x4
    [0x4]           
        Name             : System
        ThreadCount      : 0xe7
    [0x90]          
        Name             : Registry
        ThreadCount      : 0x4
...

Per vedere quali processi hanno un numero elevato di thread, ordinare l'elenco in base al numero di thread usando OrderByDescending.

0: kd> dx -r2 @$cursession.Processes.Select(p => new {Name = p.Name, ThreadCount = p.Threads.Count()}).OrderByDescending(p => p.ThreadCount)
@$cursession.Processes.Select(p => new {Name = p.Name, ThreadCount = p.Threads.Count()}).OrderByDescending(p => p.ThreadCount)                
    [0x4]           
        Name             : System
        ThreadCount      : 0xe7
    [0xa38]         
        Name             : svchost.exe
        ThreadCount      : 0x45
    [0x884]         
        Name             : MemCompression
        ThreadCount      : 0x3e

Per eseguire il rendering in una griglia formattata, modificare '-r2' in '-g'. Non è necessario specificare il livello di ricorsione, perché l'opzione griglia visualizza le colonne in modo appropriato. Infine, aggiungere l'identificatore di formato ",d" ai valori decimali di output.

0: kd> dx -g @$cursession.Processes.Select(p => new {Name = p.Name, ThreadCount = p.Threads.Count()}).OrderByDescending(p => p.ThreadCount),d
===========================================================================================
=            = Name                                                         = ThreadCount =
===========================================================================================
= [4]        - System                                                       - 231         =
= [2616]     - svchost.exe                                                  - 69          =
= [2180]     - MemCompression                                               - 62          =
= [968]      - explorer.exe                                                 - 61          =

Esempi di oggetti debugger

Questo esempio mostra i primi 5 processi che eseguono la maggior parte dei thread:

0: kd> dx -r2 Debugger.Sessions.First().Processes.Select(p => new { Name = p.Name, ThreadCount = p.Threads.Count() }).OrderByDescending(p => p.ThreadCount),5
Debugger.Sessions.First().Processes.Select(p => new { Name = p.Name, ThreadCount = p.Threads.Count() }).OrderByDescending(p => p.ThreadCount),5 

: 
    [0x4]            : 
        Name             : <Unknown Image>
        ThreadCount      : 0x73
    [0x708]          : 
        Name             : explorer.exe
        ThreadCount      : 0x2d
    [0x37c]          : 
        Name             : svchost.exe
        ThreadCount      : 0x2c
    [0x6b0]          : 
        Name             : MsMpEng.exe
        ThreadCount      : 0x22
    [0x57c]          : 
        Name             : svchost.exe
        ThreadCount      : 0x15
    [...]       

Questo esempio mostra i dispositivi nell'albero dei dispositivi plug and play raggruppati in base al nome del driver dell'oggetto dispositivo fisico. Non viene visualizzato tutto l'output.

kd> dx -r2 Debugger.Sessions.First().Devices.DeviceTree.Flatten(n => n.Children).GroupBy(n => n.PhysicalDeviceObject->Driver->DriverName.ToDisplayString())
Debugger.Sessions.First().Devices.DeviceTree.Flatten(n => n.Children).GroupBy(n => n.PhysicalDeviceObject->Driver->DriverName.ToDisplayString()) 

: 
    ["\"\\Driver\\PnpManager\""] : 
        [0x0]            : HTREE\ROOT\0
        [0x1]            : ROOT\volmgr\0000 (volmgr)
        [0x2]            : ROOT\BasicDisplay\0000 (BasicDisplay)
        [0x3]            : ROOT\CompositeBus\0000 (CompositeBus)
        [0x4]            : ROOT\vdrvroot\0000 (vdrvroot)
         ...  

Completamento automatico della scheda Comando Dx

Il completamento automatico della chiave TAB contestuale riconosce i metodi di query LINQ e funziona per i parametri delle espressioni lambda.

Ad esempio, digitare (o copiare e incollare) il testo seguente nel debugger. Premere quindi tabulazione più volte per scorrere i potenziali completamenti.

dx -r2 Debugger.Sessions.First().Processes.Select(p => new {Name = p.Name, ThreadCount = p.Threads.Count() }).OrderByDescending(p => p.

Premere TAB fino a ". Viene visualizzato il nome". Aggiungere una parentesi di chiusura ")" e premere INVIO per eseguire il comando.

kd> dx -r2 Debugger.Sessions.First().Processes.Select(p => new {Name = p.Name, ThreadCount = p.Threads.Count() }).OrderByDescending(p => p.Name)
Debugger.Sessions.First().Processes.Select(p => new {Name = p.Name, ThreadCount = p.Threads.Count() }).OrderByDescending(p => p.Name) : 
    [0x274]          : 
        Name             : winlogon.exe
        ThreadCount      : 0x4
    [0x204]          : 
        Name             : wininit.exe
        ThreadCount      : 0x2
    [0x6c4]          : 
        Name             : taskhostex.exe
        ThreadCount      : 0x8
         ...  

In questo esempio viene illustrato il completamento con un metodo di confronto della chiave. La sostituzione mostrerà i metodi stringa, poiché la chiave è una stringa.

dx -r2 Debugger.Sessions.First().Processes.Select(p => new {Name = p.Name, ThreadCount = p.Threads.Count() }).OrderByDescending(p => p.Name, (a, b) => a.

Premere TAB fino a ". Viene visualizzata la lunghezza. Aggiungere una parentesi di chiusura ")" e premere INVIO per eseguire il comando.

kd> dx -r2 Debugger.Sessions.First().Processes.Select(p => new {Name = p.Name, ThreadCount = p.Threads.Count() }).OrderByDescending(p => p.Name, (a, b) => a.Length)
Debugger.Sessions.First().Processes.Select(p => new {Name = p.Name, ThreadCount = p.Threads.Count() }).OrderByDescending(p => p.Name, (a, b) => a.Length) : 
    [0x544]          : 
        Name             : spoolsv.exe
        ThreadCount      : 0xc
    [0x4d4]          : 
        Name             : svchost.exe
        ThreadCount      : 0xa
    [0x438]          : 
        Name             : svchost.exe

Variabili definite dall'utente

Una variabile definita dall'utente può essere definita anteponendo al nome della variabile @$. Una variabile definita dall'utente può essere assegnata a qualsiasi elemento dx può usare, ad esempio espressioni lambda, risultati delle query LINQ e così via.

È possibile creare e impostare il valore di una variabile utente in questo modo.

kd> dx @$String1="Test String"

È possibile visualizzare le variabili utente definite usando Debugger.State.UserVariables o @$vars.

kd> dx Debugger.State.UserVariables
Debugger.State.UserVariables : 
    mySessionVar     : 
    String1          : Test String

È possibile rimuovere una variabile usando . Rimuovere.

kd> dx @$vars.Remove("String1")

In questo esempio viene illustrato come definire una variabile utente per fare riferimento a Debugger.Sesssions.

kd> dx @$mySessionVar = Debugger.Sessions

La variabile definita dall'utente può quindi essere usata come illustrato di seguito.

kd> dx -r2 @$mySessionVar 
@$mySessionVar   : 
    [0x0]            : Remote KD: KdSrv:Server=@{<Local>},Trans=@{COM:Port=\\.\com3,Baud=115200,Timeout=4000}
        Processes        : 
        Devices     

Variabili definite dal sistema

Le variabili definite dal sistema seguenti possono essere usate in qualsiasi query LINQ dx.

  • @$cursession - Sessione corrente

  • @$curprocess - Processo corrente

  • @$curthread - Thread corrente

In questo esempio viene illustrato l'uso delle variabili definite dal sistema.

kd> dx @$curprocess.Threads.Count()
@$curprocess.Threads.Count() : 0x4
kd> dx -r1 @$curprocess.Threads
@$curprocess.Threads : 
    [0x4adc]         : 
    [0x1ee8]         : 
    [0x51c8]         : 
    [0x62d8]         : 
     ...

Variabili definite dall'utente - Tipi anonimi

Questa creazione di oggetti dinamici viene eseguita usando la sintassi del tipo anonimo C# (new { ... }). Per altre informazioni sui tipi anonimi, vedere Tipi anonimi (Guida per programmatori C#). In questo esempio viene creato un tipo anonimo con un valore integer e stringa.

kd> dx -r1 new { MyInt = 42, MyString = "Hello World" }
new { MyInt = 42, MyString = "Hello World" } : 
    MyInt            : 42
    MyString         : Hello World

Oggetti Funzione (espressioni lambda)

Molti dei metodi usati per eseguire query sui dati si basano sul concetto di esecuzione ripetuta di una funzione fornita dall'utente tra gli oggetti di una raccolta. Per supportare la possibilità di eseguire query e modificare i dati nel debugger, il comando dx supporta espressioni lambda usando la sintassi C# equivalente. Un'espressione lambda viene definita dall'utilizzo dell'operatore => come indicato di seguito:

(arguments) => (risultato)

Per vedere come viene usato LINQ con dx, provare questo semplice esempio per aggiungere insieme 5 e 7.

kd> dx ((x, y) => (x + y))(5, 7) 

Il comando dx restituisce l'espressione lambda e visualizza il risultato di 12.

((x, y) => (x + y))(5, 7)  : 12

Questa espressione lambda di esempio combina le stringhe "Hello" e "World".

kd> dx ((x, y) => (x + y))("Hello", "World")
((x, y) => (x + y))("Hello", "World") : HelloWorld

Sintassi LINQ supportata - Metodi di query

Qualsiasi oggetto che dx definisce come iterabile (sia che una matrice nativa, un tipo con NatVis scritto come contenitore o un oggetto di estensione del debugger) abbia una serie di metodi LINQ (o LINQ equivalenti) proiettati su di esso. Questi metodi di query sono descritti di seguito. Le firme degli argomenti ai metodi di query sono elencate dopo tutti i metodi di query.

Metodi di filtro

. Where ( PredicateMethod ): restituisce una nuova raccolta di oggetti contenenti ogni oggetto nell'insieme di input per cui il metodo predicato ha restituito true.

Metodi di proiezione

. Flatten ( [KeyProjectorMethod] ): accetta un contenitore di input di contenitori (un albero) e lo appiattisce in un singolo contenitore con ogni elemento nell'albero. Se viene fornito il metodo di proiettore chiave facoltativo, l'albero viene considerato un contenitore di chiavi che sono contenitori e tali chiavi vengono determinate da una chiamata al metodo di proiezione.

. Select ( KeyProjectorMethod ): restituisce una nuova raccolta di oggetti contenente il risultato della chiamata al metodo proiettore su ogni oggetto nell'insieme di input.

Metodi di raggruppamento

. GroupBy ( KeyProjectorMethod, [KeyComparatorMethod]: restituisce una nuova raccolta di raccolte raggruppando tutti gli oggetti nell'insieme di input con la stessa chiave determinata chiamando il metodo del proiettore chiave. È possibile specificare un metodo di confronto facoltativo.

Join (InnerCollection, metodo selettore di chiavi esterne, metodo selettore chiave interna, metodo selettore risultato, [ComparatorMethod]: aggiunge due sequenze in base alle funzioni del selettore chiave ed estrae coppie di valori. È anche possibile specificare un metodo di confronto facoltativo.

Intersect (InnerCollection, [ComparatorMethod]): restituisce l'intersezione del set, ovvero gli elementi visualizzati in ognuna di due raccolte. È anche possibile specificare un metodo di confronto facoltativo.

Union (InnerCollection, [ComparatorMethod]: restituisce l'unione set, ovvero elementi univoci visualizzati in una delle due raccolte. È anche possibile specificare un metodo di confronto facoltativo.

Metodi del set di dati

Contiene (Oggetto, [ComparatorMethod]: determina se una sequenza contiene un elemento specificato. È possibile specificare un metodo di confronto facoltativo che verrà chiamato ogni volta che l'elemento viene confrontato con una voce nella sequenza.

Distinct ([ComparatorMethod]): rimuove i valori duplicati da una raccolta. È possibile specificare un metodo di confronto facoltativo da chiamare ogni volta che gli oggetti della raccolta devono essere confrontati.

Tranne (InnerCollection, [ComparatorMethod]: restituisce la differenza impostata, ovvero gli elementi di una raccolta che non vengono visualizzati in una seconda raccolta. È possibile specificare un metodo di confronto facoltativo.

Concat (InnerCollection): concatena due sequenze per formare una sequenza.

Metodi di ordinamento

. OrderBy ( KeyProjectorMethod, [KeyComparatorMethod] ): ordina l'insieme in ordine crescente in base a una chiave fornita chiamando il metodo di proiezione chiave su ogni oggetto nell'insieme di input. È possibile specificare un metodo di confronto facoltativo.

. OrderByDescending ( KeyProjectorMethod, [KeyComparatorMethod]: ordina l'insieme in ordine decrescente in base a una chiave, come indicato chiamando il metodo di proiezione chiave su ogni oggetto dell'insieme di input. È possibile specificare un metodo di confronto facoltativo.

Metodi di aggregazione

Count (): metodo che restituisce il numero di elementi nell'insieme.

Sum ([ProjectionMethod]): calcola la somma dei valori in una raccolta. Facoltativamente, è possibile specificare un metodo proiettore per trasformare gli elementi prima che si verifichi la somma.

Ignora metodi

Skip (Count): ignora gli elementi fino a una posizione specificata in una sequenza.

SkipWhile (PredicateMethod): ignora gli elementi in base a una funzione predicato fino a quando un elemento non soddisfa la condizione.

Accetta metodi

Accetta (Conteggio): accetta elementi fino a una posizione specificata in una sequenza.

TakeWhile (PredicateMethod): accetta elementi in base a una funzione predicato fino a quando un elemento non soddisfa la condizione.

Metodi di confronto

SequenceEqual (InnerCollection, [ComparatorMethod]: determina se due sequenze sono uguali confrontando gli elementi in modo saggio. È possibile specificare un comparatore facoltativo.

Metodi di gestione degli errori

AllNonError (PredicateMethod): restituisce se tutti gli elementi non di errore di una raccolta soddisfano una determinata condizione.

FirstNonError ([PredicateMethod]: restituisce il primo elemento di una raccolta che non è un errore.

LastNonError ([PredicateMethod]: restituisce l'ultimo elemento di una raccolta che non è un errore.

Altri metodi

. All ( PredicateMethod ): restituisce se il risultato della chiamata al metodo predicato specificato su ogni elemento della raccolta di input è true.

. Any ( PredicateMethod ): restituisce se il risultato della chiamata al metodo predicato specificato su qualsiasi elemento della raccolta di input è true.

. First ( [PredicateMethod] ): Restituisce il primo elemento dell'insieme. Se il predicato facoltativo viene passato, restituisce il primo elemento della raccolta per cui una chiamata al predicato restituisce true.

. Last ( [PredicateMethod] ): Restituisce l'ultimo elemento della raccolta. Se il predicato facoltativo viene passato, restituisce l'ultimo elemento della raccolta per cui una chiamata al predicato restituisce true.

Min([KeyProjectorMethod]: Restituisce l'elemento minimo della raccolta. È possibile specificare un metodo di proiettore facoltativo per proiettare ogni metodo prima che venga confrontato con altri.

Max([KeyProjectorMethod]): Restituisce l'elemento massimo della raccolta. È possibile specificare un metodo di proiettore facoltativo per proiettare ogni metodo prima che venga confrontato con altri.

Single([PredicateMethod]: restituisce l'unico elemento dell'elenco (o un errore se la raccolta contiene più di un elemento). Se viene specificato un predicato, restituisce l'singolo elemento che soddisfa tale predicato (se più di un elemento lo soddisfa, la funzione restituisce invece un errore).

Firme degli argomenti

KeyProjectorMethod : ( obj => chiave arbitraria ) Accetta un oggetto dell'insieme e restituisce una chiave da tale oggetto.
KeyComparatorMethod: ( (a, b) => valore intero ) Accetta due chiavi e ne confronta la restituzione:

-1 se ( a < b )

0 se ( a == b)

1 se ( a > b )

PredicateMethod: ( obj => valore booleano ) Accetta un oggetto dell'insieme e restituisce true o false in base al fatto che l'oggetto soddisfi determinati criteri.

Sintassi LINQ supportata - Manipolazione delle stringhe

Tutti gli oggetti stringa hanno i metodi seguenti proiettati in essi, in modo che siano disponibili per l'uso:

Eseguire query sui metodi pertinenti & proprietà

. Contiene ( OtherString ): restituisce un valore booleano che indica se la stringa di input contiene OtherString.

. EndWith (OtherString): restituisce un valore booleano che indica se la stringa di input termina con OtherString.

Lunghezza: proprietà che restituisce la lunghezza della stringa.

. StartsWith ( OtherString ): restituisce un valore booleano che indica se la stringa di input inizia con OtherString.

. Sottostringa ( StartPos, [Length] ): restituisce una sottostringa all'interno della stringa di input a partire dalla posizione iniziale specificata. Se viene specificata la lunghezza facoltativa, la sottostringa restituita sarà della lunghezza specificata; in caso contrario, verrà visualizzata alla fine della stringa.

Metodi vari

. IndexOf ( OtherString ): restituisce l'indice della prima occorrenza di OtherString all'interno della stringa di input.

. LastIndexOf ( OtherString): restituisce l'indice dell'ultima occorrenza di OtherString all'interno della stringa di input.

Metodi di formattazione

. PadLeft ( TotalWidth ): aggiunge spazi in base alle esigenze del lato sinistro della stringa per portare la lunghezza totale della stringa alla larghezza specificata.

. PadRight ( TotalWidth ): aggiunge spazi in base alle esigenze del lato destro della stringa per portare la lunghezza totale della stringa alla larghezza specificata.

. Remove ( StartPos, [Length] ): rimuove i caratteri dalla stringa di input a partire dalla posizione iniziale specificata. Se viene specificato il parametro di lunghezza facoltativo, tale numero di caratteri verrà rimosso; altrimenti: tutti i caratteri alla fine della stringa verranno rimossi.

. Sostituisci ( SearchString, ReplaceString ): sostituisce ogni occorrenza di SearchString all'interno della stringa di input con l'oggetto ReplaceString specificato.

Proiezioni di oggetti stringa

Oltre ai metodi proiettati direttamente sugli oggetti stringa, qualsiasi oggetto che ha una conversione stringa ha il metodo seguente proiettato su di esso, rendendolo disponibile per l'uso:

. ToDisplayString ( ): restituisce una conversione stringa dell'oggetto. Si tratta della conversione stringa che verrà visualizzata in una chiamata dx per l'oggetto. È possibile fornire un identificatore di formattazione per formattare l'output di ToDisplayString. Per altre informazioni, vedere Identificatori di formato per C++ nel debugger di Visual Studio

Gli esempi seguenti illustrano l'uso degli identificatori di formato.

kd> dx (10).ToDisplayString("d")
(10).ToDisplayString("d") : 10

kd> dx (10).ToDisplayString("x")
(10).ToDisplayString("x") : 0xa

kd> dx (10).ToDisplayString("o")
(10).ToDisplayString("o") : 012

kd> dx (10).ToDisplayString("b") 
(10).ToDisplayString("b")  : 0y1010

kd> dx ("some wchar string here").ToDisplayString("su") 
("some wchar string here").ToDisplayString("su")  : "some wchar string here"

kd> dx ("some wchar string here").ToDisplayString("sub") 
("some wchar string here").ToDisplayString("sub")  : some wchar string here

Esempio di debug Plug and Play

Questa sezione illustra il modo in cui gli oggetti debugger predefiniti usati con query LINQ possono essere usati per eseguire il debug di oggetti plug and play.

Visualizzare tutti i dispositivi

Usare Flatten nell'albero dei dispositivi per visualizzare tutti i dispositivi.

 1: kd> dx @$cursession.Devices.DeviceTree.Flatten(n => n.Children)
@$cursession.Devices.DeviceTree.Flatten(n => n.Children)                
    [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)
    [0x6]            : ROOT\KDNIC\0000 (kdnic)
    [0x7]            : ROOT\UMBUS\0000 (umbus)
    [0x8]            : ROOT\ACPI_HAL\0000
...

Visualizzazione della griglia

Come per altri comandi dx, è possibile selezionare e tenere premuto (o fare clic con il pulsante destro del mouse) un comando dopo l'esecuzione e selezionare "Visualizza come griglia" o aggiungere "-g" al comando per ottenere una visualizzazione griglia dei risultati.

# 0: kd> dx -g @$cursession.Devices.DeviceTree.Flatten(n => n.Children)
=====================================================================================================================================================================================================================================================================================================================
# =                                                              = (+) DeviceNodeObject = InstancePath                                                 = ServiceName               = (+) PhysicalDeviceObject                                    = State                          = (+) Resources = (+) Children       =
=====================================================================================================================================================================================================================================================================================================================
= [0x0] : HTREE\ROOT\0                                         - {...}                - HTREE\ROOT\0                                                 -                           - 0xffffb6075614be40 : Device for "\Driver\PnpManager"        - DeviceNodeStarted (776)        - {...}        - [object Object]    =
= [0x1] : ROOT\volmgr\0000 (volmgr)                            - {...}                - ROOT\volmgr\0000                                             - volmgr                    - 0xffffb607561fbe40 : Device for "\Driver\PnpManager"        - DeviceNodeStarted (776)        - {...}        - [object Object]    =
= [0x2] : ROOT\BasicDisplay\0000 (BasicDisplay)                - {...}                - ROOT\BasicDisplay\0000                                       - BasicDisplay              - 0xffffb607560739b0 : Device for "\Driver\PnpManager"        - DeviceNodeStarted (776)        - {...}        - [object Object]    =
= [0x3] : ROOT\CompositeBus\0000 (CompositeBus)                - {...}                - ROOT\CompositeBus\0000                                       - CompositeBus              - 0xffffb607561f9060 : Device for "\Driver\PnpManager"        - DeviceNodeStarted (776)        - {...}        - [object Object]    =
...

Visualizzare i dispositivi in base allo stato

Usare Dove specificare uno stato specifico del dispositivo.

dx @$cursession.Devices.DeviceTree.Flatten(n => n.Children).Where(n => n.State <operator> <state number>)

Ad esempio, per visualizzare i dispositivi nello stato DeviceNodeStarted usare questo comando.

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

Visualizzare i dispositivi non avviati

Usare questo comando per visualizzare i dispositivi non nello stato DeviceNodeStarted.

1: kd>  dx @$cursession.Devices.DeviceTree.Flatten(n => n.Children).Where(n => n.State != 776)
@$cursession.Devices.DeviceTree.Flatten(n => n.Children).Where(n => n.State != 776)                
    [0x0]            : ACPI\PNP0C01\1
    [0x1]            : ACPI\PNP0000\4&215d0f95&0
    [0x2]            : ACPI\PNP0200\4&215d0f95&0
    [0x3]            : ACPI\PNP0100\4&215d0f95&0
    [0x4]            : ACPI\PNP0800\4&215d0f95&0
    [0x5]            : ACPI\PNP0C04\4&215d0f95&0
    [0x6]            : ACPI\PNP0700\4&215d0f95&0 (fdc)
    [0x7]            : ACPI\PNP0C02\1
    [0x8]            : ACPI\PNP0C02\2

Visualizzare i dispositivi in base al codice del problema

Usare l'oggetto DeviceNodeObject.Problem per visualizzare i dispositivi con codici di problema specifici.

dx @$cursession.Devices.DeviceTree.Flatten(n => n.Children).Where(n => n.DeviceNodeObject.Problem <operator> <problemCode>)

Ad esempio, per visualizzare i dispositivi con codice non zero problema, usare questo comando. In questo modo vengono fornite informazioni simili a "!devnode 0 21".

1: kd> dx @$cursession.Devices.DeviceTree.Flatten(n => n.Children).Where(n => n.DeviceNodeObject.Problem != 0)
@$cursession.Devices.DeviceTree.Flatten(n => n.Children).Where(n => n.DeviceNodeObject.Problem != 0)                
    [0x0]            : HTREE\ROOT\0
    [0x1]            : ACPI\PNP0700\4&215d0f95&0 (fdc)

Visualizzare tutti i dispositivi senza problemi

Usare questo comando per visualizzare tutti i dispositivi senza problemi

1: kd> dx @$cursession.Devices.DeviceTree.Flatten(n => n.Children).Where(n => n.DeviceNodeObject.Problem == 0)
@$cursession.Devices.DeviceTree.Flatten(n => n.Children).Where(n => n.DeviceNodeObject.Problem == 0)                
    [0x0]            : ROOT\volmgr\0000 (volmgr)
    [0x1]            : ROOT\BasicDisplay\0000 (BasicDisplay)
    [0x2]            : ROOT\CompositeBus\0000 (CompositeBus)
    [0x3]            : ROOT\vdrvroot\0000 (vdrvroot)
...

Visualizzare tutti i dispositivi con un problema specifico

Usare questo comando per visualizzare i dispositivi con uno stato di problema di 0x16.

1: kd> dx @$cursession.Devices.DeviceTree.Flatten(n => n.Children).Where(n => n.DeviceNodeObject.Problem == 0x16)
@$cursession.Devices.DeviceTree.Flatten(n => n.Children).Where(n => n.DeviceNodeObject.Problem == 0x16)                
    [0x0]            : HTREE\ROOT\0
    [0x1]            : ACPI\PNP0700\4&215d0f95&0 (fdc)

Visualizzare i dispositivi in base al driver di funzione

Usare questo comando per visualizzare i dispositivi in base al driver di funzione.

dx @$cursession.Devices.DeviceTree.Flatten(n => n.Children).Where(n => n.ServiceName <operator> <service name>)

Per visualizzare i dispositivi che usano un determinato driver di funzione, ad esempio atapi, usare questo comando.

1: kd> dx @$cursession.Devices.DeviceTree.Flatten(n => n.Children).Where(n => n.ServiceName == "atapi")
@$cursession.Devices.DeviceTree.Flatten(n => n.Children).Where(n => n.ServiceName == "atapi")                
    [0x0]            : PCIIDE\IDEChannel\4&10bf2f88&0&0 (atapi)
    [0x1]            : PCIIDE\IDEChannel\4&10bf2f88&0&1 (atapi)

Visualizzazione di un elenco di driver di avvio

Per visualizzare l'elenco dei driver di avvio caricati come winload, è necessario trovarsi in un contesto in cui si ha accesso a LoaderBlock e abbastanza presto loaderBlock è ancora in giro. Ad esempio, durante nt! IopInitializeBootDrivers. Un punto di interruzione può essere impostato per arrestarsi in questo contesto.

1: kd> g
Breakpoint 0 hit
nt!IopInitializeBootDrivers:
8225c634 8bff            mov     edi,edi

Usare ?? comando per visualizzare la struttura del driver di avvio.

1: kd> ?? LoaderBlock->BootDriverListHead
struct _LIST_ENTRY
 [ 0x808c9960 - 0x808c8728 ]
   +0x000 Flink            : 0x808c9960 _LIST_ENTRY [ 0x808c93e8 - 0x808a2e18 ]
   +0x004 Blink            : 0x808c8728 _LIST_ENTRY [ 0x808a2e18 - 0x808c8de0 ]

Usare l'oggetto debugger Debugger.Utility.Collections.FromListEntry per visualizzare i dati usando l'indirizzo iniziale della struttura nt!_LIST_ENTRY.

1: kd> dx Debugger.Utility.Collections.FromListEntry(*(nt!_LIST_ENTRY *)0x808c9960, "nt!_BOOT_DRIVER_LIST_ENTRY", "Link")
Debugger.Utility.Collections.FromListEntry(*(nt!_LIST_ENTRY *)0x808c9960, "nt!_BOOT_DRIVER_LIST_ENTRY", "Link")                
    [0x0]            [Type: _BOOT_DRIVER_LIST_ENTRY]
    [0x1]            [Type: _BOOT_DRIVER_LIST_ENTRY]
    [0x2]            [Type: _BOOT_DRIVER_LIST_ENTRY]
    [0x3]            [Type: _BOOT_DRIVER_LIST_ENTRY]
    [0x4]            [Type: _BOOT_DRIVER_LIST_ENTRY]
    [0x5]            [Type: _BOOT_DRIVER_LIST_ENTRY]
...

Usare l'opzione -g per creare una visualizzazione griglia dei dati.

dx -r1 -g Debugger.Utility.Collections.FromListEntry(*(nt!_LIST_ENTRY *)0x808c9960, "nt!_BOOT_DRIVER_LIST_ENTRY", "Link")

Visualizzare i dispositivi in base alla funzionalità

Visualizzare i dispositivi usando l'oggetto DeviceNodeObject.CapabilityFlags.

dx -r1 @$cursession.Devices.DeviceTree.Flatten(n => n.Children).Where(n => (n.DeviceNodeObject.CapabilityFlags & <flag>) != 0)

Questa tabella riepiloga l'uso del comando dx con flag comuni di funzionalità del dispositivo.

Removibile

dbgcmd 0: kd> dx -r1 @$cursession. Devices.DeviceTree.Flatten(n => n.Children). Where(n => (n.DeviceNodeObject.CapabilityFlags & 0x10) != 0) @$cursession. Devices.DeviceTree.Flatten(n => n.Children). Where(n => (n.DeviceNodeObject.CapabilityFlags & 0x10) != 0)
[0x0] : SWD\PRINTENUM{2F8DBBB6-F246-4D84-BB1D-AA8761353885} [0x1] : SWD\PRINTENUM{F210BC77-55A1-4FCA-AA80-013E2B408378} [0x2] : SWD\PRINTENUM{07940A8E-11F4-46C3-B714-7FF9B87738F8} [0x3] : DISPLAY\Default_Monitor\6&1a097cd8&0&UID5527112 (monitor)

UniqueID

dbgcmd 0: kd> dx -r1 @$cursession. Devices.DeviceTree.Flatten(n => n.Children). Where(n => (n.DeviceNodeObject.CapabilityFlags & 0x40) != 0) @$cursession. Devices.DeviceTree.Flatten(n => n.Children). Where(n => (n.DeviceNodeObject.CapabilityFlags & 0x40) != 0)
[0x0] : HTREE\ROOT\0 [0x1] : ROOT\volmgr\0000 (volmgr) [0x2] : ROOT\spaceport\0000 (spaceport) ...

SilentInstall

dbgcmd 0: kd> dx -r1 @$cursession. Devices.DeviceTree.Flatten(n => n.Children). Where(n => (n.DeviceNodeObject.CapabilityFlags & 0x80) != 0) @$cursession. Devices.DeviceTree.Flatten(n => n.Children). Where(n => (n.DeviceNodeObject.CapabilityFlags & 0x80) != 0)
[0x0] : HTREE\ROOT\0 [0x1] : ROOT\volmgr\0000 (volmgr) [0x2] : ROOT\spaceport\0000 (spaceport) ...

RawDeviceOk

dbgcmd 0: kd> dx -r1 @$cursession. Devices.DeviceTree.Flatten(n => n.Children). Where(n => (n.DeviceNodeObject.CapabilityFlags & 0x100) != 0) @$cursession. Devices.DeviceTree.Flatten(n => n.Children). Where(n => (n.DeviceNodeObject.CapabilityFlags & 0x100) != 0)
[0x0] : HTREE\ROOT\0 [0x1] : SWD\MMDEVAPI\MicrosoftGSWavetableSynth [0x2] : SWD\IP_TUNNEL_VBUS\IP_TUNNEL_DEVICE_ROOT ...

SorpresaRemovalOK

dbgcmd 0: kd> dx -r1 @$cursession. Devices.DeviceTree.Flatten(n => n.Children). Where(n => (n.DeviceNodeObject.CapabilityFlags & 0x200) != 0) @$cursession. Devices.DeviceTree.Flatten(n => n.Children). Where(n => (n.DeviceNodeObject.CapabilityFlags & 0x200) != 0)
[0x0] : SWD\MMDEVAPI\MicrosoftGSWavetableSynth [0x1] : SWD\IP_TUNNEL_VBUS\IP_TUNNEL_DEVICE_ROOT [0x2] : SWD\PRINTENUM\PrintQueues ...

Per altre informazioni sulle funzionalitàFlags, vedere DEVICE_CAPABILITIES.

Vedere anche

dx (Visualizzazione espressione del modello a oggetti debugger)

Oggetti debugger nativi in NatVis

Oggetti debugger nativi nelle estensioni JavaScript