
Una de las innovaciones de Visual Studio 2012 fue acompa帽ada por la aparici贸n de un nuevo depurador personalizado llamado Concord. Su sistema de componentes permite que los complementos VSIX personalicen el comportamiento del depurador y escriban nuevas herramientas sensibles al contexto que pueden usar el depurador para sus necesidades. Su API proporciona muchas caracter铆sticas de QOL, como la coordinaci贸n entre el c贸digo administrado / no administrado, la integraci贸n perfecta con un proceso remoto / depurado localmente, y m谩s. De hecho, 隆casi todo lo que se puede hacer en el IDE se puede hacer mediante programaci贸n utilizando la API de Concord! Cambie los valores de variables espec铆ficas sobre la marcha, llame a funciones a pedido (隆o haga que el programa salte llamadas a ellas!), 隆Los complementos pueden buscar por PDB (!), Paso a paso e incluso modificaci贸n de c贸digo! Abra el gato y aprender谩 sobre estas innovaciones poco conocidas en el campo de la construcci贸n de bicicletas.
Probablemente deber铆as comenzar desde el principio. El depurador detecta los componentes leyendo informaci贸n del archivo
vsdconfig al que hace referencia el manifiesto del complemento VSIX. A su vez,
vsdconfig indica qu茅 interfaces est谩n implementadas por los componentes del complemento y c贸mo encontrar estos componentes (enlace a un archivo .dll, indicando la clase o, en el caso de la implementaci贸n nativa, indicando CLSID. Dar茅 ejemplos en C #). Adem谩s, se indica un identificador 煤nico (GUID) para cada componente, as铆 como su "nivel". Un nivel es lo que determina en qu茅 orden se procesar谩n los complementos, as铆 como en el contexto de qu茅 proceso se cargar谩 esta implementaci贸n, en el proceso IDE o en el proceso de la aplicaci贸n depurada. Esto se debe al hecho de que algunas funcionalidades solo pueden funcionar en el contexto de un IDE, y viceversa, solo en el contexto de un proceso depurado. Algunas funciones API funcionan de la misma manera all铆 y all谩. Por lo tanto, varios componentes tienen sus propias reglas de dise帽o, ya que pueden depender de los elementos existentes del depurador, ubicados en sus niveles fijos. Para evitar incidentes, recomiendo RTFM (https://docs.microsoft.com/en-us/dotnet/api/microsoft.visualstudio.debugger.componentinterfaces?view=visualstudiosdk-2017) y experimentos independientes en una caja de arena separada, lo que no ser谩 una pena elimine si sucede algo (esto est谩 conectado, de nuevo, con un matiz as铆; en algunos casos, ni siquiera est谩 claro por qu茅 el ensamblaje o tipo no se est谩 cargando, porque todav铆a no pude encontrar d贸nde aparecer铆an los registros que se帽alar铆an el problema de forma estable. Error, por ejemplo, con referencia a una dependencia que no se puede cargar en el proceso de destino, puede aparecer en la salida st di-, o no. S茅 akuratno, tomar compromete frecuentes,
y no sentarse detr谩s de la rueda de borracho).La lista de niveles es la siguiente (dar茅 el texto en ingl茅s para que el lector no tenga incidentes al cometer actos RFTM):
Niveles de componentes IDE (valores> 100,000):
Niveles de componentes del proceso de destino (valores <99.999):
A continuaci贸n, en orden, el proceso de creaci贸n de un proyecto. Si no hubiera matices importantes, podr铆a describir este proceso m铆nimamente o omitirlo, pero las realidades son completamente diferentes: necesitamos una serie de dependencias de la biblioteca, as铆 como una herramienta para crear archivos de configuraci贸n, que por alguna raz贸n no se distribuye con VisualStudio, pero est谩 disponible solo con nuget. De hecho, ahora necesitamos pasar a la esencia. El proceso de creaci贸n y configuraci贸n de un proyecto se estructura de la siguiente manera:
- Abra Visual Studio. En mi caso, 2017 Community Edition
- Proyecto VSIX ( Visual C # -> pesta帽a Extensibilidad , o mediante b煤squeda). Llam茅moslo "HelloVSIX"
- Agregue un nuevo proyecto de biblioteca de clases en soluci贸n y ll谩melo "DebuggeePlugin"
- Ponemos la referencia en el proyecto "DebuggeePlugin" en el proyecto "HelloVSIX"
- Ponemos la referencia al ensamblado "Microsoft.VisualStudio.Debugger.Engine" en el proyecto DebuggeePlugin
- Agregue la referencia para el paquete nuget Microsoft.VSSDK.Debugger.VSDConfigTool al proyecto "DebuggeePlugin". Esta es nuestra herramienta para generar configuraciones VSD.
Ahora, estamos listos para hacer que nuestro complemento haga algo 煤til. Hagamos lo m谩s simple que se puede hacer: dejar que muestre un cuadro de mensaje que dice "Hola VSIX" cuando el proceso de destino se encuentra con un punto de entrada. Para hacer esto, necesitamos crear una clase que implemente la interfaz
IDkmEntryPointNotification , as铆 como completar varios archivos de configuraci贸n. Agregue una nueva clase p煤blica llamada DkmEntryPointNotificationService, y herede la interfaz
IDkmEntryPointNotification , y deje la implementaci贸n predeterminada por ahora:
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(); } } }
Agregue el archivo "DkmEntryPointNotificationService.vsdconfigxml" al proyecto "DebuggeePlugin". Para cada clase declarada que deber铆a recibir notificaciones a trav茅s de implementaciones de las interfaces de espacio de nombres Microsoft.VisualStudio.Debugger.ComponentInterfaces, debe tener dicho archivo. Por cierto, es posible implementar varias interfaces de este tipo a la vez en una clase. Ahora necesitamos cambiar la acci贸n de compilaci贸n de nuestro archivo ".vsdconfigxml". Para hacer esto, debe editar manualmente el archivo del proyecto (en serio). Descargamos el proyecto DebuggeePlugin y lo abrimos con el editor de estudio. Necesitamos encontrar la siguiente etiqueta XLM:
<None Include="DkmEntryPointNotificationService.vsdconfigxml" />
y mueva esta etiqueta a su propio ItemGroup, cambiando el tipo de None a VsdConfigXmlFiles:
<ItemGroup> <VsdConfigXmlFiles Include="DkmEntryPointNotificationService.vsdconfigxml" /> </ItemGroup>
Puede guardar y volver a cargar el proyecto.
Ahora, ve a las configuraciones. Lo primero que debe hacer: si el archivo vsdconfig.xsd se agrega al proyecto DebuggeePlugin, entonces debe eliminarse. Lo reemplazaremos ahora, porque es m谩s f谩cil trabajar con texto sin formato. Abra DkmEntryPointNotificationService.vsdconfigxml y reemplace el texto con lo siguiente:
<?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>
En cualquiera de estos archivos, se nos solicitar谩 que indiquemos lo siguiente:
- ComponentId: este valor se puede generar utilizando la herramienta de generaci贸n de GUID (Herramientas -> CreateGUID)
- ComponentLevel es el nivel de nuestro componente en la jerarqu铆a. Consulte la tabla anterior y la informaci贸n de ayuda sobre MSDN para seleccionar el rango de valores deseado.
- Assemblyname es el nombre de nuestro ensamblado (隆no es una soluci贸n!). En este caso, habr谩 un DebuggeePlugin
- Nombre de clase: debe indicarse, incluido el espacio de nombres en el que se encuentra la clase. En este caso, DebuggeePlugin.DkmEntryPointNotificationService
- Matriz InterfaceGroup: cada entrada en ella indica una interfaz implementada por este componente. Dentro de cada nodo de InterfaceGroup, debe haber un subnodo que indique las interfaces comunes a todos, en este grupo, filtro, pero sobre filtros m谩s adelante. Ahora solo tenemos un nodo de interfaz y lleva el nombre de la interfaz IdkmEntryPointNotification. Si tuvi茅ramos varias interfaces, habr铆a varios nodos de interfaz.
Perm铆tame recordarle que para cada clase que deber铆a recibir notificaciones del depurador, debe haber dicho archivo. Pero la diversi贸n no termina ah铆. Cada uno de estos archivos, posteriormente, se recopila en un archivo .vsdconfig en el directorio de salida del proyecto. Y deben referenciarse en el manifiesto del complemento. Esto se hace de la siguiente manera:
- Despu茅s de haber generado el archivo ".vsdconfigxml", debemos ... recopilar la soluci贸n una vez, de lo contrario no tendremos ning煤n archivo .vsdconfig en el directorio de salida del proyecto)
- Despu茅s de eso, abra el editor de texto para el archivo source.extension.vsixmanifest y agregue el siguiente c贸digo antes de cerrar la etiqueta PackageManifest:
<Assets> <Asset Type="DebuggerEngineExtension" d:Source="File" Path="DebuggeePlugin.vsdconfig" /> </Assets>
Si, despu茅s de las acciones completadas, el archivo "DebuggeePlugin.vsdconfig" aparece en el proyecto HelloVSIX, debe
RETIRARSE DEL PROYECTO y la soluci贸n debe recopilarse nuevamente, de lo contrario no se actualizar谩.
隆El trabajo preparatorio ha terminado! Puede comenzar a depurar nuestro complemento. Esto se realiza mediante el lanzamiento de una instancia experimental de VisualStudio (para proyectos VSIX, este es el objetivo de depuraci贸n predeterminado, por lo que no son necesarios pasos adicionales). En realidad, hacemos clic en Debug-> StartDebugging y vemos una instancia experimental de VisualStudio. En 茅l, por defecto, nuestro complemento ya deber铆a estar instalado. Puede verificar esto a trav茅s del men煤 Herramientas-> Extensiones y actualizaciones.
Debido al hecho de que implementamos la interfaz IDkmEntryPointNotification, tendremos que crear un proyecto de prueba en una instancia experimental de VisualStudio. En realidad, creamos un nuevo proyecto, seleccionamos
C ++ -> Aplicaci贸n de consola (elija C ++, porque los siguientes ejemplos contendr谩n detalles espec铆ficos de C ++),
ll谩melo VSIXTestApp , ejecute sin ning煤n cambio, recopile y vea que nuestra instancia experimental dej贸 de lanzar una excepci贸n dentro del m茅todo DebuggeePlugin. DkmEntryPointNotificationService.OnEntryPoint. Genial Ahora necesita mostrar el cuadro de mensaje. Para hacer esto, es necesario agregar las siguientes referencias al proyecto DebuggeePlugin:
- Microsoft.VisualStudio.Shell.15.0
- Microsoft.VisualStudio.Shell.Interop
- Microsoft.VisualStudio.Shell.Interop.8.0
- Microsoft.VisualStudio.OLE.Interop
Agregue dos usos al comienzo del archivo DkmEntryPointNotificationService.cs:
using Microsoft.VisualStudio.Shell; using Microsoft.VisualStudio.Shell.Interop;
Y agregue una llamada al m茅todo
VsShellUtilities.ShowMessageBox en el m茅todo 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); } } }
Reconstruimos, lanzamos una instancia experimental del estudio, lanzamos un proyecto de prueba y 隆listo!
隆Vemos que la instancia de prueba del estudio cre贸 MessageBox!

驴Y qu茅, de hecho, se beneficia?
Aqu铆 aprendimos c贸mo configurar un proyecto VSIX que contenga un complemento para el depurador de Visual Studio, teniendo en cuenta la mayor铆a de los matices que se interpusieron en el camino del resultado. Este es el punto de partida para un trabajo m谩s detallado. En el pr贸ximo art铆culo, le mostrar茅 otro punto importante: c贸mo se realiza la comunicaci贸n entre el IDE y los componentes de destino de depuraci贸n.
Para obtener m谩s ayuda sobre el uso de la API de Concord, puede consultar no solo MSDN, sino tambi茅n los siguientes repositorios de Microsoft en el github:
github.com/microsoft/PTVSgithub.com/Microsoft/ConcordExtensibilitySamples