Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
A sintaxe LINQ pode ser usada com os objetos do depurador para pesquisar e manipular dados. O uso da sintaxe LINQ com o comando dx permite uma experiência mais consistente em comparação com o uso de comandos do depurador. A saída e as opções são consistentes, independentemente do objeto do depurador que você está olhando. As consultas LINQ permitem que você faça perguntas como "Quais são os 5 principais processos que estão executando mais threads?".
Os objetos do depurador são projetados em um namespace enraizado no "Depurador". Processos, módulos, threads, pilhas, quadros de pilha e variáveis locais estão disponíveis para serem usados em uma consulta LINQ.
O LINQ é conceitualmente semelhante à Structured Query Language (SQL) usada para consultar bancos de dados. Você pode usar vários métodos LINQ para pesquisar, filtrar e analisar dados de depuração. A sintaxe do método LINQ C# é usada. Para obter mais informações sobre o LINQ e a sintaxe do LINQ C#, consulte Introdução ao LINQ em C#
O LINQ que é usado no suporte ao depurador usa a "sintaxe do método" do LINQ e não a "sintaxe da consulta". Você pode encontrar mais detalhes sobre as diferenças no LINQ (Language-Integrated Query).
Comandos LINQ como os seguintes podem ser usados com os objetos do depurador. Todos, . Qualquer, . Contagem, . Primeiro, . Achatar, . GroupBy, . Por último, . OrderBy, . OrderByDescending, . Selecione e . Onde. Esses métodos seguem (o mais próximo possível) a forma dos métodos LINQ do C#.
Objetos depuradores nativos
Os objetos nativos do depurador representam várias construções e comportamentos do ambiente do depurador. Exemplos de objetos do depurador são os seguintes.
- Sessão
- Tópicos / Thread
- Processos / Processo
- Quadros de pilha / Quadro de pilha
- Variáveis locais
- Módulos / Módulo
- Utilidade
- Estado
- Configurações
Você também pode trabalhar com os objetos do depurador com NatVis. Para obter mais informações, consulte Native Debugger Objects in NatVis. Para obter informações sobre como usar objetos de depurador com JavaScript, consulte Native Debugger Objects in JavaScript Extensions. Para obter informações sobre como trabalhar com C++ e os objetos de driver, consulte Visão geral do Debugger Data Model C++.
Comando Dx
Os exemplos mostrados aqui usam o comando dx, para obter mais informações sobre como trabalhar com o comando dx, consulte dx (Display Debugger Object Model Expression).
Desenvolvendo uma consulta LINQ
Uma maneira de desenvolver uma consulta de objeto do depurador LINQ é usar os links DML exibidos para explorar o modelo de dados e localizar primeiro o objeto do depurador que será usado na consulta.
Para este exemplo, gostaríamos de exibir uma lista de processos em uma sessão de depuração do kernel e o número de threads para cada um desses processos.
Para iniciar nossa exploração, podemos usar o comando dx para exibir o objeto depurador de nível superior.
0: kd> dx Debugger
Debugger
Sessions
Settings
State
Utility
Depois de selecionarmos os tópicos de nível superior, concluímos que as Sessões parecem mais interessantes, então selecionamos o link DML para revelar que contém Processos.
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
Em seguida, selecionamos mais abaixo para olhar para o processo específico e vemos que os Threads associados a esse processo estão disponíveis. Quando selecionamos Threads para um dos processos, vemos que todos os threads associados a esse processo estão disponíveis.
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]
Agora sabemos que os dados de que precisamos para exibir o número de threads associados a um processo estão disponíveis no modelo de objeto do depurador.
Para tornar a consulta LINQ um pouco mais curta, podemos usar as variáveis definidas pelo sistema descritas posteriormente neste tópico para exibir os processos associados à sessão atual.
0: kd> dx @$cursession.Processes
@$cursession.Processes
[0x0] : Idle [Switch To]
[0x4] : System [Switch To]
[0x90] : Registry [Switch To]
...
Em seguida, adicione uma instrução SELECT. Para começar, podemos especificar o campo Nome.
0: kd> dx @$cursession.Processes.Select(p => p.Name)
@$cursession.Processes.Select(p => p.Name)
[0x0] : Idle
[0x4] : System
[0x90] : Registry
...
Para o nosso cenário, também precisamos do número de threads. Como há dois campos, crie um tipo anônimo usando novo, semelhante à sintaxe de tipo anônimo do C# descrita abaixo em Variáveis definidas pelo usuário.
dx @$cursession.Processes.Select(p => new {Name = p.Name, Threads = p.Threads})
Com esse comando, 'dx' não imprime mais o nome, então adicione -r2 (percorrer dois níveis) para exibir Nome e Threads.
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
Neste ponto, estamos exibindo o nome do processo e uma lista de threads. Para exibir o ThreadCount, use o método .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
...
Para ver quais processos têm um grande número de threads, ordene a lista por contagem de threads 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
Para renderizar em uma grade formatada, altere o '-r2' para '-g'. O nível de recursão não precisa ser especificado, porque a opção de grade exibe as colunas adequadamente. Por fim, adicione o especificador de formato ',d' aos valores decimais de saída.
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 =
Exemplos de objetos do depurador
Este exemplo mostra os 5 principais processos que executam a maioria dos threads:
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
[...]
Este exemplo mostra os dispositivos na árvore de dispositivos plug and play agrupados consoante o nome do controlador do objeto de dispositivo físico. Nem toda a saída é mostrada.
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)
...
Dx Command Aba Preenchimento Automático
A autocompletação contextual da tecla TAB reconhece os métodos de consulta LINQ e funcionará para parâmetros de expressões lambda.
Como exemplo, digite (ou copie e cole) o seguinte texto no depurador. Em seguida, pressione a tecla TAB várias vezes para navegar por possíveis conclusões.
dx -r2 Debugger.Sessions.First().Processes.Select(p => new {Name = p.Name, ThreadCount = p.Threads.Count() }).OrderByDescending(p => p.
Pressione a tecla TAB até ". Nome" aparece. Adicione um parêntese de fechamento ")" e pressione enter para executar o 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
...
Este exemplo mostra a conclusão com um método comparador de chaves. A substituição mostrará métodos de cadeia de caracteres, uma vez que a chave é uma cadeia de caracteres.
dx -r2 Debugger.Sessions.First().Processes.Select(p => new {Name = p.Name, ThreadCount = p.Threads.Count() }).OrderByDescending(p => p.Name, (a, b) => a.
Pressione a tecla TAB até aparecer ".Length". Adicione um parêntese de fechamento ")" e pressione enter para executar o 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
Variáveis definidas pelo usuário
Uma variável definida pelo usuário pode ser definida prefixando o nome da variável com @$. Uma variável definida pelo usuário pode ser atribuída a qualquer coisa que o dx possa utilizar, por exemplo, lambdas, os resultados de consultas LINQ, etc.
Você pode criar e definir o valor de uma variável de usuário como esta.
kd> dx @$String1="Test String"
Você pode exibir as variáveis de usuário definidas usando Debugger.State.UserVariables ou @$vars.
kd> dx Debugger.State.UserVariables
Debugger.State.UserVariables :
mySessionVar :
String1 : Test String
Você pode remover uma variável usando . Remover.
kd> dx @$vars.Remove("String1")
Este exemplo mostra como definir uma variável de usuário para fazer referência a Debugger.Sesssions.
kd> dx @$mySessionVar = Debugger.Sessions
A variável definida pelo usuário pode então ser usada como mostrado abaixo.
kd> dx -r2 @$mySessionVar
@$mySessionVar :
[0x0] : Remote KD: KdSrv:Server=@{<Local>},Trans=@{COM:Port=\\.\com3,Baud=115200,Timeout=4000}
Processes :
Devices
Variáveis definidas pelo sistema
As seguintes variáveis definidas pelo sistema podem ser usadas em qualquer consulta LINQ dx.
@$cursession - A sessão atual
@$curprocess - O processo atual
@$curthread - O tópico atual
Este exemplo mostra o uso das variáveis definidas pelo sistema.
kd> dx @$curprocess.Threads.Count()
@$curprocess.Threads.Count() : 0x4
kd> dx -r1 @$curprocess.Threads
@$curprocess.Threads :
[0x4adc] :
[0x1ee8] :
[0x51c8] :
[0x62d8] :
...
Variáveis definidas pelo usuário - tipos anônimos
Essa criação de objetos dinâmicos é feita usando a sintaxe de tipo anônimo C# (new { ... }). Para obter mais informações, consulte sobre tipos anônimos, consulte Tipos anônimos (Guia de programação em C#). Este exemplo cria um tipo anônimo com um valor inteiro e de cadeia de caracteres.
kd> dx -r1 new { MyInt = 42, MyString = "Hello World" }
new { MyInt = 42, MyString = "Hello World" } :
MyInt : 42
MyString : Hello World
Objetos de função (expressões do Lambda)
Muitos dos métodos usados para consultar dados são baseados no conceito de executar repetidamente uma função fornecida pelo usuário entre objetos em uma coleção. Para suportar a capacidade de consultar e manipular dados no depurador, o comando dx suporta expressões lambda usando a sintaxe C# equivalente. Uma expressão lambda é definida pelo uso do operador => da seguinte maneira:
(argumentos) => (resultado)
Para ver como o LINQ é usado com o dx, tente este exemplo simples para adicionar 5 e 7.
kd> dx ((x, y) => (x + y))(5, 7)
O comando dx repete a expressão lambda e exibe o resultado de 12.
((x, y) => (x + y))(5, 7) : 12
Este exemplo de expressão lambda combina as cadeias de caracteres "Hello" e "World".
kd> dx ((x, y) => (x + y))("Hello", "World")
((x, y) => (x + y))("Hello", "World") : HelloWorld
Sintaxe LINQ suportada - Métodos de consulta
Qualquer objeto que o dx define como iterável (seja uma matriz nativa, um tipo que tenha NatVis escrito descrevendo-o como um contêiner ou um objeto de extensão do depurador) tem uma série de métodos LINQ (ou equivalente ao LINQ) projetados nele. Esses métodos de consulta são descritos abaixo. As assinaturas dos argumentos para os métodos de consulta são listadas após todos os métodos de consulta.
Métodos de filtragem
. Where ( PredicateMethod ): Retorna uma nova coleção de objetos contendo todos os objetos da coleção de entrada para os quais o método predicado retornou true.
Métodos de Projeção
. Nivelar ( [KeyProjectorMethod] ): Pega um contêiner de entrada de contêineres (uma árvore) e o nivela em um único contêiner que tem todos os elementos na árvore. Se o método opcional para projeção de chaves for fornecido, a árvore é considerada uma estrutura de chaves que são elas próprias estruturas, e essas chaves são determinadas por uma chamada ao método de projeção.
. Select ( KeyProjectorMethod ): Retorna uma nova coleção de objetos contendo o resultado da chamada do método do projetor em cada objeto da coleção de entrada.
Métodos de agrupamento
. GroupBy ( KeyProjectorMethod, [KeyComparatorMethod] )): Retorna uma nova coleção de coleções agrupando todos os objetos na coleção de entrada com a mesma chave determinada chamando o método do projetor de chave. Pode ser fornecido um método comparador opcional.
Join (InnerCollection, Outer key selector method, Inner key selector method, Result selector method, [ComparatorMethod]): associa duas sequências com base em funções de seleção de chave e extrai pares de valores. Também pode ser especificado um método comparador opcional.
Intersect (InnerCollection, [ComparatorMethod]): retorna a interseção do conjunto, o que significa elementos que aparecem em cada uma das duas coleções. Também pode ser especificado um método comparador opcional.
Union (InnerCollection, [ComparatorMethod]): retorna a união do conjunto, o que significa elementos exclusivos que aparecem em qualquer uma das duas coleções. Também pode ser especificado um método comparador opcional.
Métodos de conjunto de dados
Contains (Object, [ComparatorMethod]): Determina se uma sequência contém um elemento especificado. Pode ser fornecido um método comparador opcional que será chamado cada vez que o elemento for comparado com uma entrada na sequência.
Distinct ([ComparatorMethod]): Remove valores duplicados de uma coleção. Um método comparador opcional pode ser fornecido para ser chamado cada vez que os objetos na coleção devem ser comparados.
Except (InnerCollection, [ComparatorMethod]): Devolve a diferença de conjunto, o que significa os elementos de uma coleção que não aparecem numa segunda coleção. Pode ser especificado um método de comparação opcional.
Concat (InnerCollection): Concatena duas sequências para formar uma sequência.
Métodos de encomenda
. OrderBy ( KeyProjectorMethod, [KeyComparatorMethod] ): Classifica a coleção em ordem crescente de acordo com uma chave, conforme fornecido, chamando o método de projeção de chave em cada objeto da coleção de entrada. Pode ser fornecido um método comparador opcional.
. OrderByDescending ( KeyProjectorMethod, [KeyComparatorMethod] ): Classifica a coleção em ordem decrescente de acordo com uma chave, conforme fornecido, chamando o método de projeção de chave em cada objeto da coleção de entrada. Pode ser fornecido um método comparador opcional.
Métodos de agregação
Count (): Um método que retorna o número de elementos na coleção.
Soma ([ProjectionMethod]): Calcula a soma dos valores em uma coleção. Opcionalmente, pode especificar um método de projetor para transformar os elementos antes que a soma ocorra.
Saltar métodos
Ignorar (Contar): ignora elementos até a uma posição especificada numa sequência.
SkipWhile (PredicateMethod): ignora elementos com base em uma função de predicado até que um elemento não satisfaça a condição.
Métodos de Captura
Take (Contar): Toma elementos até uma posição especificada numa sequência.
TakeWhile (PredicateMethod): Usa elementos com base em uma função de predicado até que um elemento não satisfaça a condição.
Métodos de comparação
SequenceEqual (InnerCollection, [ComparatorMethod]): Determina se duas sequências são iguais comparando elementos de maneira paritária. Pode ser especificado um comparador opcional.
Métodos de tratamento de erros
AllNonError (PredicateMethod): Retorna informação sobre se todos os elementos sem erro de uma coleção satisfazem uma determinada condição.
FirstNonError ([PredicateMethod]): Retorna o primeiro elemento de uma coleção que não é um erro.
LastNonError ([PredicateMethod]): Retorna o último elemento de uma coleção que não é um erro.
Outros Métodos
. All ( PredicateMethod ): Retorna se o resultado da chamada do método de predicado especificado em cada elemento da coleção de entrada é true.
. Any ( PredicateMethod ): Retorna se o resultado da chamada do método de predicado especificado em qualquer elemento na coleção de entrada é true.
. First ( [PredicateMethod] ): Retorna o primeiro elemento da coleção. Se o predicado opcional for fornecido, retorna o primeiro elemento da coleção para o qual a chamada do predicado retorna verdadeiro.
. Last ( [PredicateMethod] ): Retorna o último elemento da coleção. Se o predicado opcional for passado, retorna o último elemento da coleção para o qual uma chamada ao predicado devolve verdadeiro.
Min([KeyProjectorMethod]): Retorna o elemento mínimo da coleção. Um método de projetor opcional pode ser especificado para projetar cada método antes de ser comparado a outros.
Max([KeyProjectorMethod]): Retorna o elemento máximo da coleção. Um método de projetor opcional pode ser especificado para projetar cada método antes de ser comparado a outros.
Single([PredicateMethod]): retorna o único elemento da lista (ou um erro se a coleção contiver mais de um elemento). Se um predicado for especificado, retornará o único elemento que satisfaz esse predicado (se mais de um elemento satisfazê-lo, a função retornará um erro).
Assinaturas dos argumentos
| MétodoKeyProjector : ( obj => chave arbitrária ) | Pega um objeto da coleção e retorna uma chave desse objeto. |
| KeyComparatorMethod: ( (a, b) => valor inteiro ) | Pega em duas teclas e compara-as retornando: -1 se ( a < b ) 0 se ( a == b) 1 se ( a > b ) |
| PredicateMethod: ( obj => valor booleano ) | Pega um objeto da coleção e retorna true ou false com base em se esse objeto atende a determinados critérios. |
Sintaxe LINQ suportada - Manipulação de cadeia de caracteres
Todos os objetos de cadeia de caracteres têm os seguintes métodos projetados neles, para que estejam disponíveis para uso:
Métodos relevantes de consulta & Propriedades
. Contains ( OtherString ): Retorna um valor booleano que indica se a cadeia de caracteres de entrada contém OtherString.
. EndsWith ( OtherString ): Retorna um valor booleano indicando se a cadeia de caracteres de entrada termina com OtherString.
Length: uma propriedade que retorna o comprimento da cadeia de caracteres.
. StartsWith ( OtherString ): Retorna um valor booleano indicando se a cadeia de caracteres de entrada começa com OtherString.
. Substring ( StartPos, [Length] ): Retorna uma substring dentro da string de entrada começando na posição inicial dada. Se o comprimento opcional for fornecido, a substring retornada será do comprimento especificado; caso contrário, irá até ao final da cadeia.
Métodos Diversos
. IndexOf ( OtherString ): Devolve o índice da primeira ocorrência de OtherString dentro da cadeia de entrada.
. LastIndexOf ( OtherString ): Devolve o índice da última ocorrência de OtherString dentro da cadeia de entrada.
Métodos de formatação
. PadLeft ( TotalWidth ): Adiciona espaços conforme necessário ao lado esquerdo da cadeia de caracteres para trazer o comprimento total da cadeia para a largura especificada.
. PadRight ( TotalWidth ): Adiciona espaços conforme necessário ao lado direito da cadeia de caracteres para trazer o comprimento total da cadeia de caracteres para a largura especificada.
. Remove ( StartPos, [Length] ): Remove caracteres da cadeia de caracteres de entrada começando como a posição inicial especificada. Se o parâmetro de comprimento opcional for fornecido, esse número de caracteres será removido; caso contrário, todos os caracteres até o final da cadeia de caracteres serão removidos.
. Replace ( SearchString, ReplaceString ): substitui todas as ocorrências de SearchString dentro da cadeia de entrada pela ReplaceString especificada.
Projeções de objeto String
Além dos métodos que são projetados diretamente em objetos string, qualquer objeto que tenha uma conversão de string tem o seguinte método projetado nele, tornando-o método disponível para uso:
. ToDisplayString ( ): Retorna uma conversão de cadeia de caracteres do objeto. Esta é a conversão de cadeia de caracteres que seria mostrada em uma invocação dx para o objeto. Você pode fornecer um especificador de formatação para formatar a saída de ToDisplayString. Para obter mais informações, consulte Especificadores de formato para C++ no depurador do Visual Studio
Os exemplos a seguir ilustram o uso de especificadores de 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
Exemplo de depuração Plug and Play
Esta seção ilustra como os objetos de depurador internos usados com consultas LINQ podem ser usados para depurar objetos plug and play.
Ver todos os dispositivos
Utilize Achatar na árvore de dispositivos para ver todos os dispositivos.
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
...
Grid Display
Como acontece com outros comandos dx, você pode selecionar e segurar (ou clicar com o botão direito do mouse) um comando depois que ele foi executado e selecionar "Exibir como grade" ou adicionar "-g" ao comando para obter uma visualização em grade dos resultados.
# 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] =
...
Ver dispositivos por estado
Use Onde para especificar um estado específico do dispositivo.
dx @$cursession.Devices.DeviceTree.Flatten(n => n.Children).Where(n => n.State <operator> <state number>)
Por exemplo, para exibir dispositivos no estado DeviceNodeStarted, use este 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)
...
Ver dispositivos não iniciados
Use este comando para exibir dispositivos que não estão no estado 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
Ver dispositivos por código de problema
Use o objeto DeviceNodeObject.Problem para exibir dispositivos que têm códigos de problema específicos.
dx @$cursession.Devices.DeviceTree.Flatten(n => n.Children).Where(n => n.DeviceNodeObject.Problem <operator> <problemCode>)
Por exemplo, para exibir dispositivos que têm um código de problema diferente de zero, use este comando. Isso fornece informações semelhantes 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)
Ver todos os dispositivos sem problemas
Use este comando para visualizar todos os dispositivos sem problemas
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)
...
Ver todos os dispositivos com um problema específico
Use este comando para exibir dispositivos com um estado problemático de 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)
Ver dispositivos por controlador de funções
Use este comando para visualizar dispositivos por controlador de função.
dx @$cursession.Devices.DeviceTree.Flatten(n => n.Children).Where(n => n.ServiceName <operator> <service name>)
Para visualizar dispositivos que utilizam um certo controlador de função, como atapi, use este 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)
Visualizando uma lista de controladores de arranque
Para visualizar a lista do que o winload carregou como drivers de arranque, é necessário estar num contexto onde se tenha acesso ao LoaderBlock enquanto ainda está disponível. Por exemplo, durante o nt!IopInitializeBootDrivers. Um ponto de interrupção pode ser definido para parar neste contexto.
1: kd> g
Breakpoint 0 hit
nt!IopInitializeBootDrivers:
8225c634 8bff mov edi,edi
Use o ?? comando para exibir a estrutura do driver de inicialização.
1: kd> ?? LoaderBlock->BootDriverListHead
struct _LIST_ENTRY
[ 0x808c9960 - 0x808c8728 ]
+0x000 Flink : 0x808c9960 _LIST_ENTRY [ 0x808c93e8 - 0x808a2e18 ]
+0x004 Blink : 0x808c8728 _LIST_ENTRY [ 0x808a2e18 - 0x808c8de0 ]
Use o objeto depurador Debugger.Utility.Collections.FromListEntry para exibir os dados, usando o endereço inicial da estrutura 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]
...
Use a opção -g para criar uma exibição de grade dos dados.
dx -r1 -g Debugger.Utility.Collections.FromListEntry(*(nt!_LIST_ENTRY *)0x808c9960, "nt!_BOOT_DRIVER_LIST_ENTRY", "Link")
Ver dispositivos por capacidade
Exiba dispositivos por recurso usando o objeto DeviceNodeObject.CapabilityFlags.
dx -r1 @$cursession.Devices.DeviceTree.Flatten(n => n.Children).Where(n => (n.DeviceNodeObject.CapabilityFlags & <flag>) != 0)
Esta tabela resume o uso do comando dx com sinalizadores de capacidade de dispositivo comuns.
| Removível |
|
| UniqueID |
|
| SilentInstall |
|
| RawDeviceOk |
|
| SurpresaRemovalOK |
|
Para obter mais informações sobre o CapabilityFlags, consulte DEVICE_CAPABILITIES.
Ver também
dx (Display Debugger Object Model Expression)
objetos depuradores nativos no NatVis
objetos depuradores nativos em extensões JavaScript