
Salah satu inovasi Visual Studio 2012 disertai dengan penampilan debugger kustom baru yang disebut Concord. Sistem komponennya memungkinkan plug-in VSIX untuk menyesuaikan perilaku debugger dan menulis alat baru yang peka konteks yang dapat menggunakan debugger untuk kebutuhan mereka. API-nya menyediakan banyak fitur QOL, seperti mengatur di antara kode yang dikelola / tidak dikelola, integrasi tanpa batas dengan proses jarak jauh / lokal yang dibajak, dan banyak lagi. Faktanya, hampir semua yang dapat dilakukan dalam IDE dapat dilakukan secara terprogram menggunakan Concord API! Ubah nilai variabel tertentu dengan cepat, fungsi panggilan atas permintaan (atau secara khusus membuat program lewati panggilan ke mereka!), Plugin dapat mencari dengan PDB (!), Memotong langkah-demi-langkah dan bahkan modifikasi kode! Buka kucing dan Anda akan belajar tentang inovasi yang tidak banyak diketahui di bidang konstruksi sepeda ini.
Anda mungkin harus mulai dari awal. Debugger mendeteksi komponen dengan membaca informasi dari file
vsdconfig yang dirujuk oleh manifes dari plugin VSIX. Pada gilirannya,
vsdconfig menunjukkan antarmuka mana yang diimplementasikan oleh komponen plugin dan bagaimana menemukan komponen-komponen ini (tautan ke file .dll, yang menunjukkan kelas atau, dalam hal implementasi asli, menunjukkan CLSID. Saya akan memberikan contoh dalam C #). Juga, pengidentifikasi unik (GUID) untuk setiap komponen diindikasikan, serta "level" -nya. Level adalah apa yang menentukan dalam urutan apa plugin akan diproses, serta dalam konteks proses mana implementasi ini akan dimuat - ke dalam proses IDE atau ke dalam proses aplikasi debugged. Ini disebabkan oleh kenyataan bahwa beberapa fungsionalitas hanya dapat berfungsi dalam konteks IDE, dan sebaliknya - hanya dalam konteks proses yang di-debug. Beberapa fungsi API bekerja dengan cara yang sama di sana-sini. Juga, sejumlah komponen memiliki aturan tata letak sendiri, karena mereka mungkin bergantung pada elemen debugger yang ada yang terletak di tingkat tetap mereka. Untuk menghindari insiden, saya sarankan RTFM (https://docs.microsoft.com/en-us/dotnet/api/microsoft.visualstudio.debugger.componentinterfaces?view=visualstudiosdk-2017) dan eksperimen independen dalam kotak pasir terpisah, yang tidak akan disayangkan hapus jika sesuatu terjadi (ini terhubung, sekali lagi, dengan nuansa seperti itu - dalam beberapa kasus bahkan tidak jelas mengapa perakitan atau tipe tidak memuat, karena saya masih tidak dapat menemukan di mana log akan muncul yang akan memberi sinyal masalah secara stabil. Kesalahan, misalnya, dengan merujuk pada ketergantungan yang tidak dapat dimuat ke proses target, mungkin muncul di st output di-, atau tidak. Jadilah akuratno, sering-seringlah komit,
dan tidak duduk di belakang mabuk roda).Daftar level adalah sebagai berikut (Saya akan memberikan teks dalam bahasa Inggris sehingga pembaca tidak memiliki insiden ketika melakukan tindakan RFTM):
Level komponen IDE (nilai> 100.000):
Tingkat komponen proses target (nilai <99,999):
Selanjutnya, secara berurutan, proses membuat proyek. Jika tidak ada nuansa penting, saya bisa menggambarkan proses ini minimal atau melewatkannya sama sekali, tetapi kenyataannya sangat berbeda - kita memerlukan sejumlah dependensi perpustakaan, serta alat untuk membuat file konfigurasi, yang karena alasan tertentu tidak didistribusikan dengan VisualStudio, tetapi tersedia hanya dengan nuget. Bahkan, sekarang kita perlu beralih ke esensi. Proses membuat dan menyiapkan proyek disusun sebagai berikut:
- Buka Visual Studio. Dalam kasus saya, Edisi Komunitas 2017
- Proyek VSIX ( Visual C # -> tab Extensibility , atau melalui pencarian). Sebut saja "HelloVSIX"
- Tambahkan proyek perpustakaan kelas baru dalam solusi, dan menyebutnya "DebuggeePlugin"
- Kami menempatkan referensi pada proyek "DebuggeePlugin" di proyek "HelloVSIX"
- Kami menempatkan referensi ke majelis "Microsoft.VisualStudio.Debugger.Engine" di proyek DebuggeePlugin
- Tambahkan referensi untuk paket nuget Microsoft.VSSDK.Debugger.VSDConfigTool ke proyek "DebuggeePlugin". Ini adalah alat kami untuk menghasilkan konfigurasi VSD.
Sekarang, kami siap membuat plugin kami melakukan sesuatu yang bermanfaat. Mari kita lakukan hal paling sederhana yang dapat Anda lakukan - biarkan ia menampilkan MessageBox yang mengatakan "Hello VSIX" ketika proses target menemukan titik masuk. Untuk melakukan ini, kita perlu membuat kelas yang mengimplementasikan antarmuka
IDkmEntryPointNotification , serta mengisi beberapa file konfigurasi. Tambahkan kelas publik baru yang disebut DkmEntryPointNotificationService, dan mewarisi antarmuka
IDkmEntryPointNotification , dan biarkan implementasi default untuk saat ini:
using Microsoft.VisualStudio.Debugger; using Microsoft.VisualStudio.Debugger.ComponentInterfaces; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace DebuggeePlugin { class DkmEntryPointNotificationService : IDkmEntryPointNotification { public void OnEntryPoint(DkmProcess process, DkmThread thread, DkmEventDescriptor eventDescriptor) { throw new NotImplementedException(); } } }
Tambahkan file "DkmEntryPointNotificationService.vsdconfigxml" ke proyek "DebuggeePlugin". Untuk setiap kelas yang dideklarasikan yang harus menerima pemberitahuan melalui implementasi antarmuka namespace Microsoft.VisualStudio.Debugger.ComponentInterfaces, Anda harus memiliki file seperti itu. Omong-omong, dimungkinkan untuk mengimplementasikan beberapa antarmuka seperti itu sekaligus dalam satu kelas. Sekarang kita perlu mengubah action build dari file ".vsdconfigxml" kita. Untuk melakukan ini, Anda harus mengedit file proyek secara manual (saya serius). Kami membongkar proyek DebuggeePlugin, dan membukanya dengan editor studio. Kami perlu menemukan tag XLM berikut:
<None Include="DkmEntryPointNotificationService.vsdconfigxml" />
dan pindahkan tag ini ke ItemGroup Anda sendiri, ubah jenisnya dari Tidak Ada menjadi VsdConfigXmlFiles:
<ItemGroup> <VsdConfigXmlFiles Include="DkmEntryPointNotificationService.vsdconfigxml" /> </ItemGroup>
Anda dapat menyimpan dan memuat kembali proyek.
Sekarang, buka konfigurasi. Hal pertama yang harus dilakukan: jika file vsdconfig.xsd ditambahkan ke proyek DebuggeePlugin, maka itu harus dihapus. Kami akan menggantinya sekarang, karena lebih mudah untuk bekerja dengan teks mentah. Buka DkmEntryPointNotificationService.vsdconfigxml dan ganti teks dengan yang berikut ini:
<?xml version="1.0" encoding="utf-8"?> <Configuration xmlns="http://schemas.microsoft.com/vstudio/vsdconfig/2008"> <ManagedComponent ComponentId="422413E1-450E-40A6-AE24-7E80A81CC668" ComponentLevel=^_^quot𘙮quot^_^ AssemblyName="DebuggeePlugin"> <Class Name="DebuggeePlugin.DkmEntryPointNotificationService"> <Implements> <InterfaceGroup> <NoFilter/> <Interface Name="IDkmEntryPointNotification"/> </InterfaceGroup> </Implements> </Class> </ManagedComponent> </Configuration>
Dalam file semacam itu, kami akan diminta untuk menunjukkan hal-hal berikut:
- ComponentId - nilai ini dapat dihasilkan menggunakan alat pembuatan GUID (Alat -> CreateGUID)
- ComponentLevel adalah level komponen kami dalam hierarki. Lihat tabel di atas dan bantu informasi tentang MSDN untuk memilih rentang nilai yang diinginkan.
- Assemblyname adalah nama pertemuan kami (bukan solusi!). Dalam hal ini, akan ada DebuggeePlugin
- Nama Kelas - harus ditunjukkan termasuk namespace tempat kelas tersebut berada. Dalam hal ini, DebuggeePlugin.DkmEntryPointNotificationService
- Array InterfaceGroup - setiap entri di dalamnya menunjukkan antarmuka yang diimplementasikan oleh komponen ini. Di dalam setiap simpul InterfaceGroup, harus ada sub-simpul yang menunjukkan antarmuka umum untuk semua, dalam grup ini, filter, tetapi tentang filter nanti. Sekarang kami hanya memiliki satu simpul Antarmuka, dan membawa nama antarmuka IdkmEntryPointNotification. Jika kami memiliki beberapa antarmuka, akan ada beberapa node Interface.
Biarkan saya mengingatkan Anda bahwa untuk setiap kelas yang harus menerima pemberitahuan dari debugger, harus ada file seperti itu. Tapi kesenangan tidak berakhir di sana. Setiap file seperti itu, selanjutnya, dikumpulkan dalam file .vsdconfig di direktori output proyek. Dan mereka harus dirujuk dalam manifes plugin. Ini dilakukan sebagai berikut:
- Setelah kita membentuk file ".vsdconfigxml", kita harus ... mengumpulkan solusinya sekali, kalau tidak kita tidak akan memiliki file .vsdconfig di direktori output proyek)
- Setelah itu, buka editor teks untuk file source.extension.vsixmanifest dan tambahkan kode berikut sebelum tag PackageManifest penutup:
<Assets> <Asset Type="DebuggerEngineExtension" d:Source="File" Path="DebuggeePlugin.vsdconfig" /> </Assets>
Jika, setelah tindakan selesai, file "DebuggeePlugin.vsdconfig" muncul di proyek HelloVSIX, itu harus
DIHAPUS DARI PROYEK dan solusinya harus dikumpulkan lagi, jika tidak maka tidak akan diperbarui.
Pekerjaan persiapan sudah selesai! Anda dapat mulai men-debug plugin kami. Ini dilakukan dengan memulai instance eksperimental VisualStudio (untuk proyek VSIX ini adalah target debug default, jadi tidak diperlukan langkah-langkah tambahan). Sebenarnya, kita klik Debug-> StartDebugging dan kita melihat contoh eksperimental dari VisualStudio. Di dalamnya, secara default, plugin kami harus sudah diinstal. Anda dapat memverifikasi ini melalui Alat-> Ekstensi dan menu pembaruan.
Karena kami menerapkan antarmuka IDkmEntryPointNotification, kami harus membuat proyek uji coba dalam contoh eksperimental VisualStudio. Sebenarnya, kami membuat proyek baru, pilih
C ++ -> Aplikasi Konsol (pilih C ++, karena contoh berikut ini akan berisi spesifik C ++), sebut saja
VSIXTestApp , jalankan tanpa perubahan apa pun, kumpulkan dan lihat bahwa contoh eksperimental kami berhenti melemparkan pengecualian di dalam metode DebuggeePlugin. DkmEntryPointNotificationService.OnEntryPoint. Hebat! Sekarang Anda perlu menunjukkan MessageBox. Untuk melakukan ini, perlu menambahkan referensi berikut ke proyek DebuggeePlugin:
- Microsoft.VisualStudio.Shell.15.0
- Microsoft.VisualStudio.Shell.Interop
- Microsoft.VisualStudio.Shell.Interop.8.0
- Microsoft.VisualStudio.OLE.Interop
Tambahkan dua penggunaan di awal file DkmEntryPointNotificationService.cs:
using Microsoft.VisualStudio.Shell; using Microsoft.VisualStudio.Shell.Interop;
Dan tambahkan panggilan ke metode
VsShellUtilities.ShowMessageBox di metode DkmEntryPointNotificationService.OnEntryPoint:
using Microsoft.VisualStudio.Debugger; using Microsoft.VisualStudio.Debugger.ComponentInterfaces; using Microsoft.VisualStudio.Shell; using Microsoft.VisualStudio.Shell.Interop; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace DebuggeePlugin { class DkmEntryPointNotificationService : IDkmEntryPointNotification { public void OnEntryPoint(DkmProcess process, DkmThread thread, DkmEventDescriptor eventDescriptor) { VsShellUtilities.ShowMessageBox(Microsoft.VisualStudio.Shell.ServiceProvider.GlobalProvider, "Hello VSIX", "Hello VSIX", OLEMSGICON.OLEMSGICON_INFO, OLEMSGBUTTON.OLEMSGBUTTON_OK, OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST); } } }
Kami membangun kembali, meluncurkan contoh eksperimental studio, meluncurkan proyek uji dan voila!
Kami melihat bahwa instance uji dari studio membuat MessageBox!

Dan apa manfaatnya?
Di sini kami belajar cara mengatur proyek VSIX yang berisi plug-in untuk Visual Studio debugger, dengan mempertimbangkan sebagian besar nuansa yang menghalangi hasil. Ini adalah titik awal untuk pekerjaan yang lebih detail. Pada artikel berikutnya, saya akan menunjukkan kepada Anda poin penting lainnya: bagaimana komunikasi antara IDE dan komponen target Debug dilakukan.
Untuk bantuan lebih lanjut menggunakan Concord API, Anda dapat merujuk tidak hanya ke MSDN, tetapi juga ke repositori Microsoft berikut di github:
github.com/microsoft/PTVSgithub.com/Microsoft/ConcordExtensibilitySamples