Visual Studio mit LINQPad: Project und ProjectItems

In den Artikeln der Reihe Visual Studio erweitern greifen wir von Visual Studio-Erweiterungen aus auf Elemente von Visual Studio zu. Leider ist das Debuggen dieser Erweiterungen äußerst mühsam. Zum Debuggen müssen Sie nämlich immer erst eine weitere Visual Studio-Instanz erstellen, welche dann die Erweiterungen enthält und zum Testen bereitstellt. Fällt eine Änderung an, müssen Sie das Debuggen beenden, die Änderungen einarbeiten und erneut starten. Da wäre es doch praktisch, wenn man einfach nur eine Instanz von Visual Studio öffnen und die darauf zugreifenden Methoden direkt testen könnte. Genau das realisieren wir in diesem Artikel, wo wir das Tool LINQPad nutzen. Dieses haben wir bereits in früheren Artikeln verwendet.

Wer von Access und dem VBA-Editor kommt, findet das Debuggen unter Visual Studio bisweilen anstrengend. Im Visual Basic Editor war das alles viel einfacher: Man konnte einfach eine Prozedur in ein Standardmodul schreiben, die Einfügemarke in der Prozedur platzieren und diese mit der Taste F5 starten. Damit konnte man sogar während der Entwicklung auf Elemente des Visual Studio Editors selbst zugreifen! Und genau das wollen wir mit Visual Studio auch tun, um uns die Objekte, Methoden und Eigenschaften, die für die Programmierung von Visual Studio notwendig sind, besser kennenzulernen und schnell ausprobieren zu können.

Eine Möglichkeit dazu finden wir über das Tool LINQPad. Dieses erlaubt die Eingabe von Prozeduren und die direkte Ausführung mit der Taste F5 – genau so, wie Sie es auch von Access und dem VBA-Editor kennen.

LINQPad können Sie in einer kostenlosen Version unter https://www.linqpad.net/ herunterladen. Wenn Sie damit einfache VB-Prozeduren ausführen wollen, wechseln Sie im Auswahlfeld Language auf VB Program. Dadurch wird direkt eine leere Prozedur namens Main angelegt, die wir mit einer einfachen Debug.Print-Anweisung füllen. Diese ist übrigens automatisch verfügbar, ohne dass Sie zuvor einen Verweis auf den Namespace System.Diagnostics hinzufügen müssen. Wenn Sie dann die Einfügemarke in der Prozedur platzieren und auf die Start-Schaltfläche klicken oder die Taste F5 betätigen, führt LINQPad die Prozedur aus und das Ergebnis landet im Results-Bereich von LINQPad (siehe Bild 1).

Einfache Eingabe von Prozeduren

Bild 1: Einfache Eingabe von Prozeduren

Visual Studio fernsteuern

Nun wollen wir von LINQPad aus die aktuelle Visual Studio-Instanz fernsteuern. Dazu benötigen wir zunächst zwei Verweise.

Diese fügen wir über einen Dialog hinzu, den wir mit der Taste F4 öffnen. Der nun erscheinende Dialog Query Properties enthält eine Schaltfläche namens Add…, mit der wir einen weiteren Dialog namens Add Custom Assembly References anzeigen.

Hier können Sie die angezeigte Liste aller verfügbaren Verweise schnell durch die Eingabe der Buchstaben env filtern, sodass nur noch die Einträge aus Bild 2 erscheinen. Hier wählen Sie die beiden Einträge EnvDTE.dll und EnvDTE80.dll aus und schließen den Dialog mit der OK-Schaltfläche.

Hinzufügen von Verweisen

Bild 2: Hinzufügen von Verweisen

Danach zeigt der Dialog Query Properties die hinzugefügten Verweise an (siehe Bild 3). Damit können Sie auch diesen Dialog schließen.

Neu hinzugefügte Verweise

Bild 3: Neu hinzugefügte Verweise

Referenzieren des Visual Studio-Objekts

Das oberste Element der Bibliothek zum Arbeiten mit Visual Studio ist das DTE2-Objekt.

Dieses deklarieren wir in unserer Prozedur wie folgt:

Dim objDTE As EnvDTE80.DTE2

Dann referenzieren wir es über die Methode GetActiveObject:

objDTE = System.Runtime.InteropServices.Marshal.GetActiveObject("VisualStudio.DTE.15.0")

Hier ist zu beachten, dass Sie die richtige Version angeben – hier etwa 15.0 für Visual Studio 2017. Danach können wir mit der folgenden Anweisung etwa das aktuell angezeigte Dokument in Visual Studio ausgeben lassen:

Debug.Print (objDTE.ActiveDocument.Name.ToString())

Das Ergebnis sieht schließlich wie in Bild 4 aus. Gemessen daran, wie lange es dauert, einen Zugriff auf Elemente der Benutzeroberfläche von Visual Studio auszuprobieren, wenn wir diese innerhalb einer Visual Studio-Erweiterung testen, geschieht dies außerdem rasend schnell. Damit haben wir also ein Werkzeug, um uns komfortabel die Elemente des Objektmodells für den Zugriff auf Visual Studio anzusehen.

Zugriff auf Visual Studio

Bild 4: Zugriff auf Visual Studio

Elemente des DTE2-Objekts

Das DTE2-Objekt hat folgende für uns interessante Eigenschaften:

  • ActiveDocument: Liefert einen Verweis auf das aktuell aktive Codefenster (Beispiel siehe oben)
  • ActiveSolutionProjects: Liefert eine Auflistung aller aktuell markierten Projekte, also auch solche Projekte, von denen mindestens ein Element markiert ist:
         For Each objProject In objDTE.ActiveSolutionProjects
             Debug.Print(objProject.Name)
         Next objProject
  • ActiveWindow: Liefert einen Verweis auf das aktive Fenster – arbeitet ähnlich wie ActiveDocument.
  • CommandBars: Enthält eine Auflistung aller Menüs von Visual Studio.
         Dim i As Integer    
         For i = 1 To objDTE.CommandBars.Count()
             Debug.Print(objDTE.CommandBars.Item(i).Name)
         Next i
  • Documents: Auflistung aller geöffneten Dokumente, die gezählt oder deren Einträge ausgegeben werden können:
         Debug.Print (objDTE.Documents.Count.ToString())
         Dim objDocument As EnvDTE.Document
         For Each objDocument In objDTE.Documents
             Debug.Print (objDocument.Name)
         Next objDocument
  • ItemOperations: Objekt, das einige interessante Methoden für den Zugriff auf die Elemente des Projekts liefert, zum Beispiel AddExistingItem zum Hinzufügen einer vorhandenen Datei zum Projekt oder AddNewItem zum Erstellen eines neuen Elements auf Basis des gewünschten Typs.
  • SelectedItems: Liefert eine Liste der markierten Einträge des Projektmappen-Explorers:
         Dim objItem As EnvDTE.SelectedItem
         For Each objItem In objDTE.SelectedItems
             Debug.Print (objItem.Name)
         Next objItem
  • Solution: Liefert das Solution-Objekt aus dem Objektmappen-Explorer:
         Debug.Print (objDTE.Solution.FullName.ToString())
  • StatusBar: Liefert den aktuellen Inhalt der Statusleiste oder erlaubt das Einstellen des Inhalts. Wenn Sie einmal längere Operationen in Visual Studio per Erweiterung erledigen, können Sie den Benutzer in der Statusleiste darüber informieren:
         Debug.Print (objDTE.StatusBar.Text)
         objDTE.StatusBar.Text = "Fertig."
  • ToolWindows: Ermöglicht den Zugriff auf die ToolWindows von Visual Studio, und zwar über jeweils eigene Eigenschaften für jedes der verfügbaren Toolwindows CommandWindow, ErrorList, OutputWindow, SolutionExplorer, TaskList und ToolBox:
         ''Text an CommandWindow senden
         objDTE.ToolWindows.CommandWindow.SendInput("Test", False)
         ''Anzahl der markierten Objekte im Projektmappen-Explorer ausgeben
         Debug.Print (objDTE.ToolWindows.SolutionExplorer.SelectedItems.Length.ToString())
         ''Ausgabe des aktiven Tabs in der Toolbox
         Debug.Print (objDTE.ToolWindows.GetToolWindow("ToolBox").ActiveTab.Name)

Die Beispiele hierzu finden Sie in der Datei VisualStudioProgrammieren_DTE.linq.

ItemOperations: Elemente hinzufügen und mehr

Die ItemOperations-Eigenschaft des DTE2-Objekts bietet zum Beispiel verschiedene Möglichkeiten, Elemente zu einem Projekt hinzuzufügen:

  • AddExistingItem: Fügt eine bereits auf der Festplatte existierende Datei zu einem Projekt hinzu, die als Parameter angegeben werden muss und arbeitet somit wie der Kontextmenü-Befehl Hinzufügen|Vorhandenes Element… des Projekt-Elements. Wenn mehr als ein Element im Projektmappen-Explorer markiert ist, wird ein Fehler ausgelöst:
         objDTE.ItemOperations.AddExistingItem("C:\...\Beispieldatei.txt")
  • AddNewItem: Fügt ein neues Element zum aktuell markierten Projekt beziehungsweise zu dem Projekt des aktuell markierten Elements im Projektmappen-Explorer hinzu und ersetzt somit den Kontextmenü-Befehl Hinzufügen|Neues Element… des Projekt-Elements. Den mit diesem Kontextmenü-Eintrag aufgerufenen Dialog benötigen Sie aber dennoch, um genaue Bezeichnung für das hinzuzufügende Element herauszufinden. Diesen als ersten Parameter übergebenen Ausdruck stellen Sie aus der Kategorie und der Vorlage zusammen, also zum Beispiel wie in Bild 5 Allgemeine Elemente\Code\Modul. Sie stellen also einen durch das Backslash-Zeichen (\) getrennt die Kategorie oder Kategorien und die Elementbezeichnung zusammen. Das zweite Argument ist der Name des hinzuzufügenden Elements:
  • Diese Elemente geben Sie auch bei der AddNewItem-Methode an.

    Bild 5: Diese Elemente geben Sie auch bei der AddNewItem-Methode an.

         objDTE.ItemOperations.AddNewItem("Allgemeine Elemente\Code\Modul", "mdlBeispiel.vb")
  • IsFileOpen: Diese Funktion liefert den Wert True, wenn die als Parameter angegebene Datei in Visual Studio geöffnet ist, aber nicht im Projektmappen-Explorer angezeigt wird. Sie liefert den Wert False, wenn die Datei entweder nicht in Visual Studio geöffnet ist oder aber dort geöffnet ist und im Projektmappen-Explorer erscheint. Beispiel für einen Aufruf:
         Debug.Print(objDTE.ItemOperations.IsFileOpen("C:\...\Beispieldatei.txt"))
  • Navigate: Navigiert in einem neuen Tab in Visual Studio zu der angegebenen Adresse. Hier können Sie eine Internetadresse angeben, aber auch den Pfad zu einer Datei. Dabei wird immer das aktuelle Fenster in Visual Studio als Ziel verwendet:
         objDTE.ItemOperations.Navigate("http://www.access-im-unternehmen.de")
         objDTE.ItemOperations.Navigate("C:\...\Beispieldatei.txt")
  • NewFile: Legt ein neues Element in Visual Studio an, ohne es auf der Festplatte zu speichern. Der erste Parameter erwartet die Angabe der Vorlage (wie bereits bei AddNewItem beschrieben), der zweite den Namen. Wenn Sie keinen Parameter anlegen, wird eine Textdatei namens TextFile1.txt angelegt:
         objDTE.ItemOperations.NewFile()
  • OpenFile: Öffnet eine Datei von der Festplatte in Visual Studio. Die Parameter stimmen mit denen von NewFile überein.

Möchten Sie weiterlesen? Dann lösen Sie Ihr Ticket!
Hier geht es zur Bestellung des Jahresabonnements des Magazins DATENBANKENTWICKLER:
Zur Bestellung ...
Danach greifen Sie sofort auf alle rund 200 Artikel unseres Angebots zu - auch auf diesen hier!
Oder haben Sie bereits Zugangsdaten? Dann loggen Sie sich gleich hier ein:

Schreibe einen Kommentar