Bagikan melalui


Menggunakan LINQ Dengan objek debugger

Sintaks LINQ dapat digunakan dengan objek debugger untuk mencari dan memanipulasi data. Menggunakan sintaks LINQ dengan perintah dx memungkinkan pengalaman yang lebih konsisten dibandingkan dengan menggunakan perintah debugger. Output dan opsi konsisten terlepas dari objek debugger mana yang Anda amati. Kueri LINQ memungkinkan Anda mengajukan pertanyaan seperti "Apa 5 proses teratas yang menjalankan utas terbanyak?".

Objek debugger diproyeksikan ke dalam namespace yang berakar pada "Debugger". Proses, modul, utas, tumpukan, bingkai tumpukan, dan variabel lokal semuanya tersedia untuk digunakan dalam kueri LINQ.

LINQ secara konseptual mirip dengan Structured Query Language (SQL) yang digunakan untuk mengkueri database. Anda dapat menggunakan sejumlah metode LINQ untuk mencari, memfilter, dan mengurai data debug. Sintaks metode LINQ C# digunakan. Untuk informasi selengkapnya tentang sintaks LINQ dan LINQ C#, lihat Memulai LINQ di C#

LINQ yang digunakan dalam dukungan debugger menggunakan "sintaks metode" LINQ dan bukan "sintaks kueri". Anda dapat menemukan detail selengkapnya tentang perbedaan dalam LINQ (Language-Integrated Query).

Perintah LINQ seperti berikut ini dapat digunakan dengan objek debugger. .Semua, .Apapun, .Hitung, .Pertama, .Ratakan, .KelompokkanDengan, .Terakhir, .OrderBy, .OrderByDescending, .Pilih, dan .Mana. Metode ini mengikuti (sedekat mungkin) formulir metode C# LINQ.

Objek debugger asli

Objek debugger asli mewakili berbagai konstruksi dan perilaku lingkungan debugger. Contoh objek debugger mencakup yang berikut ini.

  • Sesi
  • Utas / Utas
  • Proses / Proses
  • Bingkai Tumpukan
  • Variabel Lokal
  • Modul / Modul
  • Utilitas
  • Negara
  • Pengaturan

Anda juga dapat bekerja dengan objek debugger dengan NatVis. Untuk informasi selengkapnya, lihat Objek Debugger Asli di NatVis. Untuk informasi tentang menggunakan objek debugger dengan JavaScript, lihat Objek Debugger Asli di Ekstensi JavaScript. Untuk informasi tentang bekerja dengan C++ dan objek driver, lihat Gambaran Umum Debugger Data Model C++.

Perintah Dx

Contoh yang diperlihatkan di sini menggunakan perintah dx, untuk informasi selengkapnya tentang bekerja dengan perintah dx, lihat dx (Ekspresi Model Objek Debugger Tampilan).

Mengembangkan Kueri LINQ

Salah satu cara untuk mengembangkan kueri objek debugger LINQ adalah dengan menggunakan tautan DML yang ditampilkan untuk menjelajahi model data untuk terlebih dahulu menemukan objek debugger yang akan digunakan dalam kueri.

Untuk contoh ini, kami ingin menampilkan daftar proses dalam sesi debug kernel dan jumlah utas untuk masing-masing proses tersebut.

Untuk memulai eksplorasi, kita dapat menggunakan perintah dx untuk menampilkan objek debugger tingkat atas.

0: kd> dx Debugger
Debugger
    Sessions
    Settings
    State
    Utility

Setelah memilih topik tingkat atas, kami menentukan bahwa Sesi terlihat paling menarik, jadi kami memilih tautan DML untuk mengungkapkan bahwa itu berisi Proses.

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

Kemudian kami memilih lebih jauh ke bawah untuk melihat proses tertentu dan kami melihat bahwa Utas yang terkait dengan proses tersebut tersedia. Ketika kita memilih Utas untuk salah satu proses, kita melihat bahwa semua utas yang terkait dengan proses tersebut tersedia.

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] 

Kita sekarang tahu bahwa data yang kita butuhkan untuk menampilkan jumlah utas yang terkait dengan proses tersedia dalam model objek debugger.

Untuk membuat kueri LINQ sedikit lebih pendek, kita dapat menggunakan Variabel yang Ditentukan Sistem yang dijelaskan nanti dalam topik ini untuk menampilkan proses yang terkait dengan sesi saat ini.

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

Selanjutnya tambahkan pernyataan SELECT. Untuk memulai, kita dapat menentukan bidang Nama.

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

Untuk skenario kami, kami juga membutuhkan jumlah utas. Karena ada dua bidang, buat jenis anonim menggunakan baru, mirip dengan sintaks tipe anonim C#yang dijelaskan di bawah ini dalam Variabel yang Ditentukan Pengguna.

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

Dengan perintah itu, 'dx' tidak benar-benar mencetak nama lagi, jadi tambahkan -r2 (dua tingkat berulang) untuk menampilkan nama dan proses.

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       

Saat ini kami menampilkan nama proses dan daftar thread. Untuk menampilkan ThreadCount, gunakan metode .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
...

Untuk melihat proses mana yang memiliki sejumlah besar utas, urutkan daftar menurut jumlah utas menggunakan 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

Untuk merender dalam kisi berformat, ubah '-r2' menjadi '-g'. Tingkat rekursi tidak perlu ditentukan, karena opsi kisi menampilkan kolom dengan tepat. Terakhir, tambahkan penentu format ',d' untuk menghasilkan nilai desimal.

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          =

Contoh Objek Debugger

Contoh ini menunjukkan 5 proses teratas yang menjalankan jumlah utas terbanyak:

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
    [...]       

Contoh ini menunjukkan perangkat di pohon perangkat plug and play yang dikelompokkan berdasarkan nama driver objek perangkat fisik. Tidak semua output ditampilkan.

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)
         ...  

Penyelesaian Otomatis Perintah Tab Dx

Penyelesaian otomatis kontekstual dengan tombol TAB mengenali metode kueri LINQ dan akan berfungsi untuk parameter dari ekspresi lambda.

Sebagai contoh, ketik (atau salin dan tempel) teks berikut ke debugger. Kemudian tekan tombol TAB beberapa kali untuk menelusuri potensi penyelesaian.

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

Tekan tombol TAB hingga ". Nama" muncul. Tambahkan tanda kurung penutup ")" dan tekan enter untuk menjalankan perintah.

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
         ...  

Contoh ini menunjukkan penyelesaian dengan metode komparator kunci. Penggantian akan menampilkan metode string, karena kuncinya adalah string.

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

Tekan tombol TAB hingga ". Panjang" muncul. Tambahkan tanda kurung penutup ")" dan tekan enter untuk menjalankan perintah.

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

Variabel yang Ditentukan Pengguna

Variabel yang ditentukan pengguna dapat ditentukan dengan awalan nama variabel dengan @$. Variabel yang ditentukan pengguna dapat ditetapkan ke apa pun yang dapat digunakan dx, misalnya, lambda, hasil kueri LINQ, dll.

Anda dapat membuat dan mengatur nilai variabel pengguna seperti ini.

kd> dx @$String1="Test String"

Anda dapat menampilkan variabel pengguna yang ditentukan menggunakan Debugger.State.UserVariables atau @$vars.

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

Anda dapat menghapus variabel menggunakan .Remove.

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

Contoh ini menunjukkan cara menentukan variabel pengguna untuk mereferensikan Debugger.Sesssions.

kd> dx @$mySessionVar = Debugger.Sessions

Variabel yang ditentukan pengguna kemudian dapat digunakan seperti yang ditunjukkan di bawah ini.

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

Variabel yang Ditentukan Sistem

Variabel yang ditentukan sistem berikut dapat digunakan dalam kueri dx LINQ apa pun.

  • @$cursession - Sesi saat ini

  • @$curprocess - Proses saat ini

  • @$curthread - Utas saat ini

Contoh ini menunjukkan penggunaan variabel yang ditentukan sistem.

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

Variabel yang Ditentukan Pengguna - Jenis Anonim

Pembuatan objek dinamis ini dilakukan menggunakan sintaks tipe anonim C# (baru { ... }). Untuk informasi selengkapnya lihat tentang jenis anonim, lihat Jenis Anonim (Panduan Pemrograman C#). Contoh ini membuat jenis anonim dengan bilangan bulat dan nilai string.

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

Objek Fungsi (Ekspresi Lambda)

Banyak metode yang digunakan untuk mengkueri data didasarkan pada konsep berulang kali menjalankan fungsi yang disediakan pengguna di seluruh objek dalam koleksi. Untuk mendukung kemampuan untuk mengkueri dan memanipulasi data dalam debugger, perintah dx mendukung ekspresi lambda menggunakan sintaks C# yang setara. Ekspresi lambda didefinisikan oleh penggunaan operator => sebagai berikut:

(argumen) => (hasil)

Untuk melihat bagaimana LINQ digunakan dengan dx, coba contoh sederhana ini untuk menambahkan bersama-sama 5 dan 7.

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

Perintah dx mengulangi ekspresi lambda dan menampilkan hasil berupa 12.

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

Contoh ekspresi lambda ini menggabungkan string "Hello" dan "World".

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

Sintaks LINQ yang Didukung - Metode Kueri

Setiap objek yang didefinisikan oleh dx sebagai iterable (baik itu array bawaan, tipe yang memiliki NatVis yang menjelaskannya sebagai kontainer, atau objek ekstensi debugger) memiliki serangkaian metode LINQ (atau setara LINQ) yang diprojeksi padanya. Metode kueri tersebut dijelaskan di bawah ini. Tanda tangan argumen untuk metode kueri tertera setelah semua metode kueri.

Metode Pemfilteran

. Di mana ( PredicateMethod ): Mengembalikan kumpulan objek baru yang berisi setiap objek dalam koleksi input yang metode predikatnya mengembalikan true.

Metode Proyeksi

. Flatten ( [KeyProjectorMethod] ): Mengambil sebuah kontainer yang berisi kontainer-kontainer (sebuah pohon) dan meratakannya menjadi satu kontainer yang mencakup setiap elemen dalam pohon. Jika metode proyeksi kunci opsional disediakan, pohon dianggap sebagai kontainer untuk kunci-kunci yang juga merupakan kontainer itu sendiri dan kunci-kunci tersebut ditentukan melalui pemanggilan metode proyeksi.

. Pilih ( KeyProjectorMethod ): Mengembalikan kumpulan objek baru yang berisi hasil pemanggilan metode proyektor pada setiap objek dalam koleksi input.

Metode Pengelompokan

. GroupBy ( KeyProjectorMethod, [KeyComparatorMethod] ): Mengembalikan kumpulan koleksi baru dengan mengelompokkan semua objek dalam koleksi input yang memiliki kunci yang sama seperti yang ditentukan dengan memanggil metode proyektor kunci. Metode komparator opsional dapat disediakan.

Join (InnerCollection, Metode pemilih kunci luar, Metode pemilih kunci dalam, Metode pemilih hasil, [ComparatorMethod]): Menggabungkan dua urutan berdasarkan fungsi pemilih kunci dan mengekstrak pasangan nilai. Metode komparator opsional juga dapat ditentukan.

Intersect (InnerCollection, [ComparatorMethod]): Mengembalikan irisan yang ditetapkan, yang berarti elemen yang muncul di masing-masing dari dua koleksi. Metode komparator opsional juga dapat ditentukan.

Union (InnerCollection, [ComparatorMethod]): Mengembalikan himpunan gabungan, yang berarti elemen-elemen unik yang muncul di salah satu atau kedua dari dua koleksi. Metode komparator opsional juga dapat ditentukan.

Metode Himpunan Data

Berisi (Objek, [MetodePerbandingan]): Menentukan apakah suatu urutan mengandung elemen tertentu. Metode komparator opsional dapat disediakan yang akan dipanggil setiap kali elemen dibandingkan dengan entri dalam urutan.

Berbeda ([ComparatorMethod]): Menghapus nilai duplikat dari koleksi. Metode komparator opsional dapat disediakan untuk dipanggil setiap kali objek dalam koleksi harus dibandingkan.

Kecuali (InnerCollection, [ComparatorMethod]): Mengembalikan perbedaan yang ditetapkan, yang berarti elemen dari satu koleksi yang tidak muncul dalam koleksi kedua. Metode komparator opsional dapat ditentukan.

Concat (InnerCollection): Menggabungkan dua urutan untuk membentuk satu urutan.

Metode Pemesanan

. OrderBy ( KeyProjectorMethod, [KeyComparatorMethod] ): Mengurutkan koleksi dalam urutan naik sesuai dengan kunci seperti yang disediakan dengan memanggil metode proyeksi kunci pada setiap objek dalam koleksi input. Metode komparator opsional dapat disediakan.

. OrderByDescending ( KeyProjectorMethod, [KeyComparatorMethod] ): Mengurutkan koleksi dalam urutan menurun sesuai dengan kunci seperti yang disediakan dengan memanggil metode proyeksi kunci pada setiap objek dalam koleksi input. Metode komparator opsional dapat disediakan.

Metode Pengagregasian

Count (): Metode yang mengembalikan jumlah elemen dalam koleksi.

Jumlah ([ProjectionMethod]): Menghitung jumlah nilai dalam koleksi. Dapat secara opsional menentukan metode proyektor untuk mengubah elemen sebelum penjumlahan terjadi.

Lewati Metode

Lewati (Hitungan): Lewati elemen hingga posisi tertentu secara berurutan.

SkipWhile (PredicateMethod): Melompati elemen berdasarkan fungsi predikat hingga elemen tidak memenuhi kondisi.

Ambil Metode

Pilih (Hitungan): Memilih elemen hingga posisi tertentu dalam urutan.

TakeWhile (PredicateMethod): Mengambil elemen berdasarkan fungsi predikat sampai elemen tidak memenuhi kondisi.

Metode Perbandingan

SequenceEqual (InnerCollection, [ComparatorMethod]): Menentukan apakah dua urutan sama dengan membandingkan elemen secara sepasang. Komparator opsional dapat ditentukan.

Metode Penanganan Kesalahan

AllNonError (PredicateMethod): Mengembalikan apakah semua elemen non-kesalahan dari koleksi memenuhi kondisi tertentu.

FirstNonError ([PredicateMethod]): Mengembalikan elemen pertama dari koleksi yang bukan merupakan kesalahan.

LastNonError ([PredicateMethod]): Mengembalikan elemen terakhir dari koleksi yang bukan merupakan kesalahan.

Metode Lain

. Semua ( PredicateMethod ): Mengembalikan apakah hasil pemanggilan metode predikat yang ditentukan pada setiap elemen dalam koleksi input adalah benar.

. Any ( PredicateMethod ): Mengembalikan apakah hasil pemanggilan metode predikat yang ditentukan pada elemen apa pun dalam koleksi input adalah benar.

. Pertama ( [PredicateMethod] ): Mengembalikan elemen pertama dalam koleksi. Jika predikat opsional diteruskan, mengembalikan elemen pertama dalam koleksi yang memenuhi predikat.

. Terakhir ( [PredicateMethod] ): Mengembalikan elemen terakhir dalam koleksi. Jika predikat opsional diberikan, akan mengembalikan elemen terakhir dalam koleksi di mana panggilan ke predikat tersebut menghasilkan nilai true.

Min([KeyProjectorMethod]): Mengembalikan elemen minimum koleksi. Metode proyektor opsional dapat ditentukan untuk memproyEkusikan setiap metode sebelum dibandingkan dengan metode lain.

Max([KeyProjectorMethod]): Mengembalikan elemen maksimum koleksi. Metode proyektor opsional dapat ditentukan untuk memproyEkusikan setiap metode sebelum dibandingkan dengan metode lain.

Single([PredicateMethod]): Mengembalikan satu-satunya elemen dari daftar (atau kesalahan jika koleksi berisi lebih dari satu elemen). Jika predikat ditentukan, mengembalikan elemen tunggal yang memenuhi predikat tersebut (jika lebih dari satu elemen memenuhinya, fungsi mengembalikan kesalahan sebagai gantinya).

Tanda tangan Argumen

KeyProjectorMethod : ( obj => kunci arbitrer ) Mengambil objek koleksi dan mengembalikan kunci dari objek tersebut.
KeyComparatorMethod: ( (a, b) => nilai bilangan bulat ) Mengambil dua kunci dan membandingkannya kembali:

-1 jika ( a < b )

0 jika ( a == b)

1 jika ( a > b )

PredicateMethod: ( obj => nilai boolean ) Mengambil objek koleksi dan mengembalikan true atau false berdasarkan apakah objek tersebut memenuhi kriteria tertentu.

Sintaks LINQ yang didukung - Manipulasi String

Semua objek string memiliki metode berikut yang diproyeksikan ke dalamnya, sehingga tersedia untuk digunakan:

Kueri Metode & Properti yang Relevan

. Berisi ( OtherString ): Mengembalikan nilai boolean yang menunjukkan apakah string input berisi OtherString.

. EndsWith ( OtherString ): Mengembalikan nilai boolean yang menunjukkan apakah string input berakhir dengan OtherString.

Panjang: Properti yang mengembalikan panjang string.

. StartsWith ( OtherString ): Mengembalikan nilai boolean yang menunjukkan apakah string input dimulai dengan OtherString.

. Substring ( StartPos, [Length] ): Mengembalikan substring dalam string input yang dimulai pada posisi awal yang diberikan. Jika panjang opsional disediakan, substring yang dikembalikan akan memiliki panjang yang ditentukan; jika tidak - itu akan pergi ke akhir string.

Metode Beragam

. IndexOf ( OtherString ): Mengembalikan indeks kemunculan pertama OtherString dalam string input.

. LastIndexOf ( OtherString ): Mengembalikan indeks kemunculan terakhir OtherString dalam string input.

Metode Pemformatan

. PadLeft ( TotalWidth ): Menambahkan spasi seperlunya ke sisi kiri string untuk membawa panjang total string ke lebar yang ditentukan.

. PadRight ( TotalWidth ): Menambahkan spasi seperlunya ke sisi kanan string untuk membawa panjang total string ke lebar yang ditentukan.

. Hapus ( StartPos, [Length] ): Menghapus karakter dari string input yang dimulai sebagai posisi awal yang ditentukan. Jika parameter panjang opsional disediakan, jumlah karakter tersebut akan dihapus; jika tidak – semua karakter di akhir string akan dihapus.

. Ganti ( SearchString, ReplaceString ): Mengganti setiap kemunculan SearchString dalam string input dengan ReplaceString yang ditentukan.

Proyeksi Objek String

Selain metode yang diproyeksikan langsung ke objek string, objek apa pun yang memiliki konversi string memiliki metode berikut yang diproyeksikan ke dalamnya, membuatnya tersedia untuk digunakan:

. ToDisplayString ( ): Mengembalikan konversi string objek. Ini adalah konversi string yang akan ditampilkan dalam pemanggilan dx untuk objek. Anda dapat menyediakan penentu pemformatan untuk memformat output ToDisplayString. Untuk informasi selengkapnya, lihat Spesifikator format untuk C++ di debugger Visual Studio

Contoh berikut mengilustrasikan penggunaan penentu format.

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

Contoh Debugging Plug and Play

Bagian ini menggambarkan bagaimana objek debugger bawaan yang digunakan dengan kueri LINQ, dapat digunakan untuk men-debug objek plug and play.

Lihat semua perangkat

Gunakan Ratakan pada pohon perangkat untuk melihat semua perangkat.

 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
...

Tampilan Kisi

Seperti halnya perintah dx lainnya, Anda dapat memilih dan menahan (atau mengklik kanan) perintah setelah dijalankan dan memilih "Tampilkan sebagai kisi" atau menambahkan "-g" ke perintah untuk mendapatkan tampilan kisi hasil.

# 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]    =
...

Lihat Perangkat menurut Status

Gunakan Tempat untuk menentukan status perangkat tertentu.

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

Misalnya untuk melihat perangkat dalam status DeviceNodeStarted, gunakan perintah ini.

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)
...

Lihat Perangkat yang Tidak Dimulai

Gunakan perintah ini untuk melihat perangkat yang tidak dalam status 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

Lihat Perangkat menurut Kode Masalah

Gunakan objek DeviceNodeObject.Problem untuk melihat perangkat yang memiliki kode masalah tertentu.

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

Misalnya, untuk melihat perangkat yang memiliki kode masalah bukan nol, gunakan perintah ini. Ini memberikan informasi serupa dengan "!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)

Lihat Semua Perangkat Tanpa Masalah

Gunakan perintah ini untuk melihat semua perangkat tanpa masalah

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)
...

Lihat Semua Perangkat Dengan Masalah Tertentu

Gunakan perintah ini untuk melihat perangkat dengan status masalah 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)

Lihat Perangkat menurut Driver Fungsi

Gunakan perintah ini untuk melihat perangkat menurut driver fungsi.

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

Untuk melihat perangkat yang menggunakan driver fungsi tertentu, seperti atapi, gunakan perintah ini.

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)

Menampilkan Daftar Driver Boot Start

Untuk melihat daftar apa yang dimuat oleh winload sebagai driver yang dimuat pada saat boot awal, Anda harus berada dalam konteks di mana Anda memiliki akses ke LoaderBlock dan pada saat yang cukup dini ketika LoaderBlock masih ada. Misalnya, selama nt!IopInitializeBootDrivers. Titik henti dapat diatur untuk berhenti dalam konteks ini.

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

Gunakan ?? perintah untuk menampilkan struktur driver boot.

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

Gunakan objek debugger Debugger.Utility.Collections.FromListEntry untuk melihat data, menggunakan alamat awal struktur 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]
...

Gunakan opsi -g untuk membuat tampilan kisi data.

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

Melihat perangkat menurut Kemampuan

Lihat perangkat berdasarkan kemampuan menggunakan objek DeviceNodeObject.CapabilityFlags.

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

Tabel ini meringkas penggunaan perintah dx dengan bendera kemampuan perangkat umum.

Dapat dilepas

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 ...

SurpriseRemovalOK

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 ...

Untuk informasi selengkapnya tentang CapabilityFlags, lihat DEVICE_CAPABILITIES.

Lihat juga

dx (Ekspresi Model Objek Debugger Tampilan)

Objek Debugger Asli di NatVis

Objek Debugger Asli di ekstensi JavaScript