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 tidak peduli objek debugger mana yang Anda lihat. 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 Bahasa Permintaan Terstruktur (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 LINQ dan sintaks 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 (Kueri Terintegrasi Bahasa).

Perintah LINQ seperti berikut ini dapat digunakan dengan objek debugger. Semua. Apa saja, . Menghitung. Pertama. Meratakan. GroupBy, . 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 termasuk yang berikut ini.

  • Sesi
  • Utas / Utas
  • Proses/ Proses
  • Bingkai Tumpukan / Bingkai Tumpukan
  • Variabel Lokal
  • Modul / Modul
  • Utilitas
  • Provinsi
  • 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 kita pilih lebih lanjut ke bawah untuk melihat proses tertentu dan kita melihat bahwa Utas yang terkait dengan proses tersebut tersedia. Ketika kita memilih Utas untuk salah satu proses, kita melihat 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 pilih. Untuk memulainya, 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 kita, kita juga membutuhkan jumlah utas. Karena ada dua bidang, buat jenis anonim menggunakan baru, mirip dengan sintaks jenis 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 Utas.

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       

Pada titik ini kami menampilkan nama proses dan daftar utas. 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 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 Tab Perintah Dx

Penyelesaian otomatis kunci TAB kontekstual mengetahui metode kueri LINQ dan akan berfungsi untuk parameter lambda.

Sebagai contoh, ketik (atau salin dan tempel) teks berikut ke dalam 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 tutup ")" 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 tutup ")" 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 mengawali 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 . Menghapus.

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 nilai bilangan bulat dan 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 menggemakan kembali ekspresi lambda dan menampilkan hasil 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

Objek apa pun yang dx tentukan sebagai dapat diulang (baik itu array asli, jenis yang ditulis NatVis yang menjelaskannya sebagai kontainer, atau objek ekstensi debugger) memiliki serangkaian metode LINQ (atau setara LINQ) yang diproyeksikan ke dalamnya. Metode kueri tersebut dijelaskan di bawah ini. Tanda tangan argumen ke metode kueri dicantumkan setelah semua metode kueri.

Metode Pemfilteran

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

Metode Proyeksi

. Flatten ( [KeyProjectorMethod] ): Mengambil kontainer input kontainer (pohon) dan meratakannya ke dalam satu kontainer yang memiliki setiap elemen di pohon. Jika metode proyektor kunci opsional disediakan, pohon dianggap sebagai kontainer kunci yang merupakan kontainer itu sendiri dan kunci tersebut ditentukan oleh panggilan ke 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 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, Outer key selector method, Inner key selector method, Result selector method, [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 union yang ditetapkan, yang berarti elemen unik yang muncul di salah satu dari dua koleksi. Metode komparator opsional juga dapat ditentukan.

Metode Himpunan Data

Berisi (Objek, [ComparatorMethod]): Menentukan apakah urutan berisi 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 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 Agregat

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): Melompati elemen hingga posisi tertentu dalam urutan.

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

Ambil Metode

Ambil (Hitungan): Mengambil elemen hingga posisi tertentu secara berurutan.

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

Metode Perbandingan

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

Metode Penanganan Kesalahan

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

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

LastNonError ([PredicateMethod]): Mengembalikan elemen terakhir dari kumpulan 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 panggilan ke predikatnya mengembalikan true.

. Terakhir ( [PredicateMethod] ): Mengembalikan elemen terakhir dalam koleksi. Jika predikat opsional diteruskan, mengembalikan elemen terakhir dalam koleksi yang panggilan ke predikatnya mengembalikan true.

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

Max([KeyProjectorMethod]): Mengembalikan elemen maksimum koleksi. Metode proyektor opsional dapat ditentukan untuk memproyeksikan setiap metode sebelum dibandingkan dengan yang 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 akan 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 dengan mengembalikan:

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

Metode Yang Relevan Kueri & Properti

. 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 masuk ke akhir string.

Metode Lain-lain

. 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 sendiri 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 Format penentu 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 Plug and Play Penelusuran Kesalahan

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)

Melihat Daftar Driver Boot Start

Untuk melihat daftar winload yang dimuat sebagai driver boot start, Anda harus berada dalam konteks di mana Anda memiliki akses ke LoaderBlock dan cukup awal 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

Menggunakan ?? 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 berdasarkan Kapabilitas

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.

Removable

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} [F210BC77-55A1-4FCA-AA80-013E2B408378} [0x2 F210BC77] : 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 (Tampilkan Ekspresi Model Objek Debugger)

Objek Debugger Asli di NatVis

Objek Debugger Asli di Ekstensi JavaScript