August 2017
Band 32, Nummer 8
Visual Studio: Erstellen von Erweiterungen für mehrere Visual Studio-Versionen
Von Carlos Quintero | August 2017
Das Release einer neuen Version von Visual Studio stellt für die Entwickler von Erweiterungen (Pakete, Add-Ins, Vorlagen usw.) immer eine Herausforderung dar. Mit Visual Studio 2010 wurde z. B. der neue Visual Studio-Installer für eXtensions (VSIXDateien) eingeführt, mit Visual Studio 2012 die hellen/dunklen Designs, und Visual Studio 2015 entfernte Add-Ins (mit dem Add-In-Manager). Unabhängig davon stellt jede Visual Studio-Version ein neues SDK, neue Erweiterbarkeitsassemblys und neue APIs bereit. Mit Visual Studio 2017 wird die Herausforderung sogar aufgrund des neuen modularen Setups, das auf Arbeitsauslastungen und einzelnen Komponenten basiert, und einer neuen Version des Manifests für den VSIX-Bereitstellungsmechanismus noch größer. Während einige Entwickler (meistens von Microsoft) eine andere neue Erweiterung für jede neue Visual Studio-Version veröffentlichen, würde es die Mehrheit bevorzugen, eine aktualisierte Erweiterung für die größtmögliche Palette der Versionen von Visual Studio zu veröffentlichen.
Wie Sie dazu vorgehen müssen, erläutere ich in diesem Artikel. Dabei setze ich das wohl gängigste Szenario ein: ein Paket mit einem Befehl, das in einer verwalteten Sprache (in diesem Fall C#) erstellt und als VSIX-Datei bereitgestellt wird.
Dabei sollen die folgenden Ziele erreicht werden:
- Verwenden eines einzigen Visual Studio-Projekts zum Erstellen des Pakets.
- Verwenden von Visual Studio 2017 für die Entwicklung und das Debuggen.
- Generieren einer einzelnen Paket-DLL als Ergebnis des Builds.
- Integrieren dieser einzelnen DLL in eine einzelne VSIX-Datei.
- Möglichkeit der Installation dieser VSIX-Datei unter Visual Studio 2017 und zahlreichen früheren Versionen (2015, 2013 usw.).
Da zwei Artefakte benötigt werden – eine DLL-Datei (die das Paket darstellt) und eine VSIX-Datei (die das Bereitstellungsvehikel für das Paket ist) –, erläutere ich beide Aspekte getrennt voneinander: Zunächst stelle ich die Funktionsweise bei der Installation oder während der Laufzeit vor, dann erläutere ich den Entwicklungsvorgang.
Die VSIX-Datei
Wie bereits weiter oben erwähnt, wurde mit Visual Studio 2010 der VSIX-Bereitstellungsmechanismus für die Installation von Visual Studio-Erweiterungen eingeführt, der seitdem die bevorzugte Vorgehensweise darstellt. Eine VSIX-Datei weist die Erweiterung VSIX auf und kann auf verschiedene Weise installiert werden. Wenn die VSIX-Datei in Visual Studio Marketplace (früher Visual Studio-Katalog) veröffentlicht wird und mit der von Ihnen verwendeten Visual Studio-Version und -Edition kompatibel ist, können Sie sie mithilfe des Dialogfelds „Extensions und Updates“ installieren. Klicken Sie im Menü „Extras“ auf „Extensions und Updates“, und navigieren Sie dann zu „Online“ > „Visual Studio Marketplace“ (siehe Abbildung 1: Das Dialogfeld „Extensions und Updates“).
Abbildung 1: Das Dialogfeld „Extensions und Updates“
Sie können auch auf eine VSIX-Datei doppelklicken. Wenn dies geschieht, wird ein Visual Studio-Startprogramm (C:\Programme (x86)\Common Files\Microsoft Shared\MSEnv\VSLauncher.exe) ausgeführt, das der VSIX-Erweiterung zugeordnet ist. Dieses ermittelt das Hilfsprogramm „VSIXInstaller.exe“ der höchsten installierten Visual Studio-Version (die höchste Version muss in der Lage sein, in alle niedrigeren Versionen zu installieren). Anschließend zeigt der VSIX-Installer das Dialogfeld in Abbildung 2 an, damit Sie die kompatiblen Visual Studio-Versionen und Editionen auswählen können, in denen die Erweiterung installiert werden soll.
Abbildung 2: Der VSIX-Installer
VSIX-Dateien können auch programmgesteuert mit dem Hilfsprogramm „VSIXInstaller.exe“ über dessen Befehlszeilenoptionen, z. B. die Visual Studio-Zielversion (2017, 2015 usw.) und -Edition (Community, Professional usw.), installiert werden. Sie finden dieses Hilfsprogramm im Unterordner „Common7\IDE“ Ihrer Visual Studio-Installation.
In beiden Fällen muss Visual Studio oder das Hilfsprogramm „VSIXInstaller.exe“ die Visual Studio-Versionen und -Editionen kennen, die die VSIX-Datei unterstützt. Diese Informationen können über eine Manifestdatei innerhalb der Datei ermittelt werden. Bei der VSIX-Datei handelt es sich um eine ZIP-Datei. Sie können daher die VSIX-Erweiterung in .zip umbenennen und die Datei dann öffnen, um ihren Inhalt zu untersuchen (siehe Abbildung 3: Inhalt einer VSIX-Datei).
Abbildung 3: Inhalt einer VSIX-Datei
Wie Sie sehen können, enthält das ZIP-Archiv mehrere Dateien: Die DLL-Datei ist die Paket-DLL. Die PKGDEF-Datei wird zur Installationszeit zum Hinzufügen einiger Schlüssel zur Windows-Registrierung verwendet, die es Visual Studio ermöglichen, die DLL als ein Paket zu erkennen. Die Datei „[Content_Types].xml“ beschreibt den Inhaltstyp für jede Erweiterung (.dll, .json usw.). Die Dateien „catalog.json“ und „manifest.json“ sind für Visual Studio 2017 erforderlich. In der Datei „extension.vsixmanifest“ werden der Name der Erweiterung, die Version, weitere Informationen und die unterstützten Visual Studio-Versionen und -Editionen beschrieben.
Sie können die Datei „extension.vsixmanifest“ entzippen und mit einem Text-Editor öffnen, um ihren Inhalt zu untersuchen. Dieser ähnelt dem in Abbildung 4 gezeigten Inhalt.
Abbildung 4: Der Inhalt einer Manifestdatei
Wie Sie sehen können, gibt das Manifest im XML-Element „InstallationTarget“ die unterstützten Visual Studio-Editionen an. Hier gibt der Wert „Microsoft.VisualStudio.Pro“ die Professional-Edition oder höher an, z. B. Premium, Ultimate, Enterprise und andere solche Editionen. Beachten Sie, dass auch die Community-Edition als Ziel verwendet werden kann, die im Grunde eine Professional-Edition mit einigen Lizenzierungseinschränkungen ist und einige der Features nicht enthält. Außerdem wird der Bereich der unterstützten Visual Studio-Versionen angegeben: 10.0 (2010), 11.0 (2012), 12.0 (2013), 14.0 (2015), 15.0 (2017).
Wenn die VSIX-Datei einer Pro-Benutzer-Erweiterung installiert wird (durch Visual Studio oder durch den VSIX-Installer), werden die darin enthaltenen Dateien entzippt und in einem willkürlichen Ordner an diesem Speicherort kopiert: C:\Benutzer\<Benutzer>\AppData\Local\Microsoft\VisualStudio\<Versionsnummer>\Extensions\<Willkürlicher Ordner>. An die <Versionsnummer> kann ein Suffix „Exp“ für die „Experimentelle Instanz“ (eine Erläuterung folgt später) angefügt werden, und für Visual Studio 2017 ist außerdem die „Instanz-ID“ der installierten Visual Studio-Version enthalten. Diese Instanz-ID wird zum Zeitpunkt der Installation von Visual Studio als Zufallswert generiert. Sie wurde hinzugefügt, um parallele Installationen verschiedener Editionen der gleichen Version (2017) von Visual Studio zu unterstützen. Dies war zuvor nicht möglich. Für computerweite Erweiterungen wird der Unterordner „Common7\IDE\Extensions“ verwendet. Beachten Sie, dass in allen Fällen jede Visual Studio-Version ihren eigenen Ordner für ihre Erweiterungen verwendet.
Es wäre vorteilhaft, wenn alle Visual Studio-Versionen das gleiche Manifestformat unterstützen würden. Leider ist das nicht der Fall. Mit Visual Studio 2010 wurden VSIX und die erste Version des Manifests eingeführt. Mit Visual Studio 2012 wurde Version 2 eingeführt, die völlig anders und nicht kompatibel mit Version 1 ist. Visual Studio 2012, 2013 und 2015 (die alle Version 2 unterstützen) können jedoch noch ein Manifest der Version 1 annehmen. Sie können daher eine VSIX-Datei mit Version 1 erstellen und aus Visual Studio 2010 das Ziel Visual Studio 2015 verwenden. Visual Studio 2017 unterstützt aber weder Version 1 noch Version 2. Stattdessen ist eine dritte Version des Manifests erforderlich. Glücklicherweise verwendet Version 3 auch weiterhin der Wert „2.0.0.0“ im Attribut „Version“ des XML-Elements „PackageManifest“ und fügt nur ein XML-Element namens <Prerequisites> (und die beiden neuen Dateien „catalog.json“ und „manifest.json“ in der VSIX-Datei) hinzu. Daher besteht vollständige Abwärtskompatibilität mit der zweiten Version, die von Visual Studio 2012, 2013 und 2015 (aber nicht von Visual Studio 2010, das nur Version 1 unterstützt) unterstützt wird. Dies bedeutet, dass es nicht möglich ist, für Visual Studio 2010 bis 2017 nur eine VSIX-Datei zu verwenden. Vor diesem Hintergrund gebe ich Visual Studio 2010 auf und beschäftige mich ab jetzt mit einer VSIX-Datei, die Visual Studio 2012, 2013, 2015 und 2017 unterstützt.
Die Paket-DLL
Ein verwaltetes Visual Studio-Paket ist eine DLL, die eine Klasse enthält, die von „Microsoft.VisualStudio.Shell.Package“ erbt. Als Decorator-Elemente dienen bestimmte Attribute, die zur Buildzeit das Generieren einer PKGDEF-Datei unterstützen (die Sie wie weiter oben beschrieben in der VSIX-Datei und im Installationsordner der Erweiterung finden können). Die PKGDEF-Datei wird beim Start (ältere Versionen von Visual Studio) oder zur Installationszeit (Version 15.3 von Visual Studio 2017) zum Registrieren der DLL als ein Paket für Visual Studio verwendet. Nach der Registrierung versucht Visual Studio irgendwann, das Paket zu laden. Dies geschieht entweder beim Start oder wenn einer der Befehle ausgeführt wird, wenn das Paket verzögertes Laden verwendet (dies ist die bewährte Methode). Während des Versuchs, die verwaltete DLL zu laden und das Paket zu initialisieren, geschehen drei Dinge: Die DLL wird von der CLR (Common Language Runtime) einer Microsoft .NET Framework-Version geladen, einige von .NET Framework bereitgestellte DLLs werden verwendet, und einige von Visual Studio bereitgestellte DLLs werden verwendet. Im Folgenden werde ich jeden dieser Vorgänge untersuchen.
.NET Framework ist die Summe aus zwei Komponenten: der CLR und Bibliotheken (Basisklassen- und weitere Bibliotheken). Die CLR ist die Runtime (der JIT-Compiler, Garbage Collector usw.), und sie lädt verwaltete DLLs. Vor langer Zeit stellte jede .NET Framework-Version 1.0, 1.1 und 2.0 (verwendet von Visual Studio.NET 2002, Visual Studio.NET 2003 und Visual Studio 2005) eine eigene CLR-Version (1.0, 1.1 und 2.0) bereit. Die .NET Framework-Versionen 3.0 und 3.5 (verwendet von Visual Studio 2008) verwendeten jedoch auch weiterhin genau die gleiche CLR 2.0 von .NET Framework 2.0, anstatt eine neue CLR einzuführen. Mit Visual Studio 2010 wurden .NET Framework 4 und CLR 4.0 eingeführt. Seither haben alle neuen .NET Framework-Versionen 4.x CLR 4.0 verwendet (wenn auch ein „lokaler“ Austausch mit einer abwärtskompatiblen Version stattfand, anstatt die genaue CLR 4.0 von .NET Framework 4 erneut zu verwenden). Seit Visual Studio 2012 und höher wird einheitlich die CLR 4.0 verwendet. Die CLR-Version stellt kein Problem dar, wenn die DLL einer Erweiterung Visual Studio 2012, 2013, 2015 und 2017 als Ziel verwendet.
Bibliotheken sind der zweite Bestandteil von .NET Framework. Dabei handelt es sich um DLLs, auf die durch ein Visual Studio-Projekt verwiesen wird und die zur Laufzeit verwendet werden. Wenn Sie eine einzelne Erweiterung entwickeln möchten, die für mehrere Versionen von Visual Studio verwendet werden kann, müssen Sie die höchste Version von .NET Framework verwenden, die standardmäßig von der niedrigsten Visual Studio-Version verwendet wird, die Sie als Ziel nutzen möchten. Dies bedeutet Folgendes: Wenn Sie Visual Studio 2012 oder höher als Ziel nutzen möchten, müssen Sie .NET Framework 4.5 verwenden. Sie können z. B. nicht .NET Framework 4.5.1 verwenden, das mit Visual Studio 2013 eingeführt wurde, weil alle neuen DLLs aus dieser Version nicht auf einem Computer vorhanden sind, auf dem nur Visual Studio 2012 installiert ist. Wenn diese DLL nicht wirklich erforderlich ist, möchten Sie solche Benutzer auch nicht zwingen, .NET Framework 4.5.1 zu installieren, um Ihre Erweiterung zu verwenden (dies könnte sich negativ auf Ihre Umsätze oder auf Downloads und den Support auswirken).
Die Erweiterung benötigt außerdem DLLs, die von Visual Studio bereitgestellt werden (diese tragen normalerweise die Namen „Microsoft.VisualStudio.*“). Zur Laufzeit findet Visual Studio diese DLLs an einigen wohlbekannten Speicherorten, z. B. im Ordner „Common7\IDE“ mit seinen Unterordnern „Common7\IDE\PublicAssemblies“ und „Common7\IDE\PrivateAssemblies“ sowie im GAC (globaler Assemblycache). Der GAC für .NET Framework 4.x befindet sich unter „C:\Windows\Microsoft.NET\assembly“ (ein weiterer GAC befindet sich unter „C:\Windows\assembly“, der für ältere Versionen von .NET Framework zuständig ist). Visual Studio 2017 verwendet eine isoliertere Installation, die den GAC vermeidet und stattdessen die weiter oben beschriebenen Ordner nutzt.
Beim Entwickeln und Generieren einer VSIX-Datei sollten einige Schlüsselprinzipien beachtet werden: Sie müssen die Versionen verwenden, die von der niedrigsten Visual Studio-Version bereitgestellt werden, die Ihre Erweiterung als Ziel verwendet. Wenn das Ziel Visual Studio 2012 oder höher sein soll, bedeutet dies, dass Sie nur die Assemblys und Erweiterbarkeits-APIs verwenden dürfen, die von dieser Version (oder einer niedrigeren Version) bereitgestellt werden. Wenn Ihre Erweiterung eine DLL verwendet, die mit Visual Studio 2013 oder höher eingeführt wurde, funktioniert die Erweiterung nicht auf einem Computer, auf dem nur Visual Studio 2012 installiert ist. Das zweite Prinzip besteht darin, dass die Erweiterung niemals Visual Studio-DLLs bereitstellen darf – weder an den von mir erwähnten Speicherorten (Ordner von Visual Studio oder GAC), noch im Installationsordner der Erweiterung. Diese DLLs werden von der Visual Studio-Zielversion bereitgestellt. Die VSIX-Datei sollte sie daher nicht enthalten.
Viele Visual Studio-DLLs weisen eine Versionsnummer (8.0 … 15.0) im Namen auf, etwa „Microsoft.VisualStudio.Shell.11.0.dll“ oder „Microsoft.VisualStudio.Shell.Immutable.10.0.dll“. Diese Angaben helfen bei der Identifizierung der Visual Studio-Version, mit der sie eingeführt wurden. Lassen Sie sich aber nicht täuschen: Es handelt sich um einen Namen, nicht um eine Version. Es sind z. B. vier Versionen (11.0.0.0, 12.0.0.0, 14.0.0.0 und 15.0.0.0) von „Microsoft.Visual.Studio.Shell.11.0.dll“ vorhanden, die von jeweils einer Visual Studio-Version (2012, 2013, 2015 und 2017) bereitgestellt werden. Die ersten drei (11.0.0.0 bis 14.0.0.0) werden von der jeweiligen Visual Studio-Version im GAC installiert, und die vierte Version (15.0.0.0), die von Visual Studio 2017 verwendet wird, wird im Ordner „Common\IDE\PrivateAssemblies“ installiert.
Da eine Erweiterung mit dem Ziel Visual Studio 2012 und höher Visual Studio-Assemblys mit der Version 11.0.0.0 (das erste weiter oben genannte Prinzip) verwenden muss, bedeutet dies, dass der Verweis „Microsoft.Visual.Studio.Shell.11.0.dll“ die Version 11.0.0.0 besitzen muss. Da diese Version aber von Visual Studio 2013 oder höher nicht installiert wird (diese Versionen starten mit Version 12.0.0.0) und die Erweiterung keine Visual Studio-DLLs bereitstellen soll (das zweite Prinzip), würde dann nicht für die Erweiterung ein Fehler auftreten, wenn versucht wird, diese Visual Studio-DLL zu verwenden? Die Antwort lautet dank eines von .NET Framework bereitgestellten Mechanismus für die Assemblybindungsumleitung nein. Dieser Mechanismus ermöglicht das Angeben von Regeln (z. B. „wenn diese Version einer Assembly angefordert wird, die neuere Version davon verwenden“). Natürlich muss die neue Version vollständig abwärtskompatibel mit der alten Version sein. Es gibt mehrere Möglichkeiten, Assemblys von einer Version an eine andere umzuleiten. Dies ist eine der Möglichkeiten: Eine ausführbare Datei (EXE-Erweiterung) kann eine begleitende Konfigurationsdatei (EXE.CONFIG-Erweiterung) bereitstellen, die die Umleitungen angibt. Wenn Sie zum Ordner „Common7\IDE“ Ihrer Visual Studio-Installation navigieren, finden Sie die ausführbare Datei „devenv.exe“ von Visual Studio sowie eine Datei „devenv.exe.config“. Wenn Sie die CONFIG-Datei mit einem Text-Editor öffnen, erkennen Sie, dass sie zahlreiche Assemblyumleitungen enthält:
<dependentAssembly>
<assemblyIdentity
name="Microsoft.VisualStudio.Shell.11.0"
publicKeyToken="b03f5f7f11d50a3a"
culture="neutral"/>
<bindingRedirect
oldVersion="2.0.0.0-14.0.0.0
newVersion="15.0.0.0"/>
</dependentAssembly>
Visual Studio 2017 (15.0) verfügt also über eine Assemblyversionsumleitung für „Microsoft.VisualStudio.Shell.11.0“, die angibt, dass bei einer Anforderung der alten Versionen von 2.0.0.0 bis 14.0.0.0 stattdessen die neue Version 15.0.0.0 verwendet wird. Auf diese Weise kann Visual Studio 2013 oder höher eine Erweiterung selbst dann verwenden, die auf „Microsoft.VisualStudio.Shell.11.0“ der Version 11.0.0.0 verweist, wenn diese genaue Version nicht bereitgestellt wird.
Entwickeln der Erweiterung
Da Sie nun wissen, was zur Laufzeit geschieht, können Sie das Paket entwickeln. Rekapitulieren wir noch einmal das bereits Gesagte: Sie erstellen mithilfe von Visual Studio 2017 ein VSIX-Projekt mit einem Manifest, das als Ziel die Visual Studio-Versionen von 12.0 bis 15.0 angibt. Es enthält ein Paket und einen Befehl, und es verwendet nur Verweise mit der Version 11.0.0.0 (oder niedriger), die von Visual Studio 2012 installiert werden.
Vielleicht fragen Sie sich im Moment, welche Versionen von Visual Studio auf Ihrem Entwicklungscomputer installiert werden sollten. Eine bewährte Methode besteht darin, zwei Entwicklungscomputer wie folgt zu verwenden: Auf dem ersten Computer installieren Sie alle Visual Studio-Versionen (2012, 2013, 2015 und 2017), wenn ausreichen Platz auf dem Datenträger vorhanden ist. Diese können alle parallel koexistieren, und Sie können sie während der Entwicklung testen. Für Visual Studio 2017 können sogar verschiedene Editionen (z. B. Community, Professional und Enterprise) gleichzeitig vorhanden sein. Dies war bei älteren Versionen von Visual Studio nicht möglich. Wenn der verfügbare Speicherplatz problematisch ist, installieren Sie die minimal erforderlichen Komponenten für die alten Versionen, oder überspringen Sie eine Version in der Mitte des Bereichs (2013 oder 2015).
Installieren Sie auf dem zweiten Entwicklungscomputer nur Visual Studio 2017 oder (noch besser) einen Buildserver, auf dem keine Version von Visual Studio installiert ist (sondern nur die Build Tools 2017), um Ihre Erweiterung für das Release zu erstellen. Mit diesem Ansatz stellen Sie sicher, dass Sie nicht versehentlich DLLs oder andere Abhängigkeiten aus Ordnern verwenden, die von älteren Visual Studio-Versionen installiert werden. Vielleicht fragen Sie sich auch, ob es nicht sicherer wäre, die Entwicklung oder den Buildvorgang auf einem Computer auszuführen, auf dem nur Visual Studio 2012 installiert ist. Das ist aber nicht möglich: Zum Generieren einer VSIX-Datei für Visual Studio 2017 (bei dem ein Manifest der Version 3 erstellt und die Dateien „catalog.json“ und „manifest.json“ hinzugefügt werden) benötigen Sie das Visual Studio SDK 15.0 von Visual Studio 2017 oder bei einigen Aufgaben das Visual Studio SDK 14.0 von Visual Studio 2015. Weder das Visual Studio SDK 12.0 von Visual Studio 2013, noch das Visual Studio SDK 11.0 von Visual Studio 2012 kann VSIX-Dateien für Visual Studio 2017 erstellen.
Außerdem erfordert die bewährte Methode für (ernsthaftes) Testen Folgendes: Verwenden Sie einen separaten Computer (virtuell oder cloudbasiert) für jede Visual Studio-Version (Sie benötigen also vier Computer zum Testen Ihrer Erweiterung mit Visual Studio 2012 bis Visual Studio 2017 in einer isolierten Umgebung). Anhand dieser bewährten Methode konnte ich einige Fehler im Codebeispiel für diesen Artikel ermitteln!
Damit die Visual Studio 2017-Projektvorlage ein Paket (oder eine andere Art von Erweiterung) erstellt, benötigen Sie die Arbeitsauslastung „Visual Studio-Extensionentwicklung“. Wenn Sie diese nicht bei der Erstinstallation von Visual Studio 2017 installiert haben, navigieren Sie zum Ordner „C:\Programme (x86)\Microsoft Visual Studio\Installer“,starten Sie „vs_Installer.exe“, klicken Sie auf die Schaltfläche „Ändern“, und wählen Sie diese Arbeitsauslastung dann unten in der Liste aus.
Erstellen Sie ein neues VSIX-Projekt, indem Sie das Menü „Datei“ >“Neu“ > „Projekt“ verwenden, navigieren Sie zu „Visual C#“ > „Erweiterbarkeitsvorlagen“, stellen Sie sicher, dass Sie „.NET Framework 4.5“ in der Dropdownliste oben ausgewählt haben, und wählen Sie dann die VSIX-Projektvorlage aus. Nennen Sie das Projekt „VSIXProjectVS2012_2017“. Doppelklicken Sie auf die Datei „source.extension.vsixmanifest“, um deren benutzerdefinierten Editor zu öffnen. Legen Sie auf der Registerkarte „Metadaten“ den Produktnamen, den Autor, die Version usw. fest. Klicken Sie auf der Registerkarte „Ziele installieren“ auf die Schaltfläche „Bearbeiten“, wählen Sie den Bezeichner „Microsoft.VisualStudio.Pro“ aus (dieser Wert verwendet als Ziel auch die Community-Edition, die im Wesentlichen eine Professional-Edition ist), und legen Sie den Zielinstallationsbereich ([11.0,15.0]) wie in Abbildung 5 gezeigt fest. Eine eckige Klammer bedeutet, dass der Wert eingeschlossen ist. Eine runde Klammer würde bedeuten, dass der Wert ausgeschlossen ist. Sie können also auch [11.0,16.0) festlegen. Sie können auch eine Nebenversion (etwa 15.3) als Ziel angeben, indem Sie die Buildnummer (z. B. 15.0.26208.1) verwenden.
Abbildung 5: Installationsziele
Löschen Sie auf der Registerkarte „Abhängigkeiten“ alle Elemente. Klicken Sie auf der Registerkarte „Voraussetzungen“ auf die Schaltfläche „Bearbeiten“, und legen Sie die minimale Visual Studio 2017-Komponente fest, die für Ihre Erweiterung erforderlich ist. In diesem Beispiel ist nur der Kern-Editor von Visual Studio erforderlich. Dieser Abschnitt ist in Visual Studio 2017 und im Manifest der Version 3 neu und gilt daher nur für Version 15.0 (siehe Abbildung 6: Voraussetzungen):
Abbildung 6: Voraussetzungen
Fügen Sie das Paket dem VSIX-Projekt hinzu, indem Sie im Projektmappen-Explorer mit der rechten Maustaste auf den VSIX-Projektknoten klicken, und wählen Sie dann das Menü „Hinzufügen“ > „Neues Element“ aus, um das Dialogfeld „Neues Element hinzufügen“ zu öffnen. Navigieren Sie nun zum Knoten „Visual Studio C#-Elemente“ > „Erweiterbarkeit“ > „VSPackage“, wählen Sie die Visual Studio-Paketvorlage aus, und nennen Sie diese „MyPackage.cs“. Fügen Sie dem Paket einen Befehl hinzu, indem Sie die Aktionen des vorherigen Schritts wiederholen, dieses Mal aber die Vorlage „Benutzerdefinierter Befehl“ auswählen. Nennen Sie diese Datei „MyCommand1.cs“.
Gemäß dem Prinzip, die wenigsten Abhängigkeiten zu verwenden, die erforderlich sind, entfernen Sie im Quellcode von „MyPackage.cs“ und „MyCommand1.cs“ die nicht verwendeten (grau hinterlegten) Namespaces. Klicken Sie anschließend im Projektmappen-Explorer mit der rechten Maustaste auf den VSIX-Projektknoten, und klicken Sie dann auf den Eintrag „NuGet-Pakete für Projektmappe verwalten“. Deinstallieren Sie im Abschnitt „Installiert“ alle Pakete in der hier gezeigten Reihenfolge:
Microsoft.VisualStudio.Shell.15.0
Microsoft.VisualStudio.Shell.Framework
Microsoft.VisualStudio.CoreUtility
Microsoft.VisualStudio.Imaging
Microsoft.VisualStudio.Shell.Interop.12.0
Microsoft.VisualStudio.Shell.Interop.11.0
Microsoft.VisualStudio.Shell.Interop.10.0
Microsoft.VisualStudio.Threading
Microsoft.VisualStudio.Shell.Interop.9.0
Microsoft.VisualStudio.Shell.Interop.8.0
Microsoft.VisualStudio.TextManager.Interop.8.0
Microsoft.VisualStudio.Shell.Interop
Microsoft.VisualStudio.TextManager.Interop
Microsoft.VisualStudio.Validation
Microsoft.VisualStudio.Utilities
Microsoft.VisualStudio.OLE.Interop
(Deinstallieren Sie nicht das Paket „Microsoft.VSSDK.BuildTools“, das das Visual Studio SDK enthält.)
Deinstallieren Sie im Projektmappen-Explorer im Knoten „Verweise“ des Projekts alle restlichen Verweise (die nicht als NuGet-Pakete abgerufen wurden) mit Ausnahme von „System“ und „System.Design“. Nun können Sie die Projektmappe erneut erstellen. Sie erhalten Kompilierungsfehler, die durch Hinzufügen nur der in Abbildung 7 gezeigten Verweise behoben werden.
Abbildung 7: Visual Studio 2012-Verweise
Assemblyname | Assemblyversion | Unterordner „Visual Studio 2012 SDK“ |
Microsoft.VisualStudio.OLE.Interop | 7.1.40304.0 | v2.0 |
Microsoft.VisualStudio.Shell.Interop | 7.1.40304.0 | v2.0 |
Microsoft.VisualStudio.Shell.Interop.8.0 | 8.0.0.0 | v2.0 |
Microsoft.VisualStudio.Shell.Interop.9.0 | 9.0.0.0 | v2.0 |
Microsoft.VisualStudio.Shell.Interop.10.0 | 10.0.0.0 | v2.0 |
Microsoft.VisualStudio.Shell.Immutable.10.0 | 10.0.0.0 | v4.0 |
Microsoft.VisualStudio.Shell.11.0 | 11.0.0.0 | v4.0 |
Leider stellt Microsoft kein offizielles NuGet-Paket für „Microsoft.VisualStudio.Shell.11.0“ bereit (es ist jedoch ein inoffizielles NuGet-Paket „VSSDK.Shell.11“ verfügbar). Wenn Sie Visual Studio 2012 installiert haben (dies sollte der Falls sein, wenn dies die mindestens unterstützte Version für Ihre Erweiterung ist), können Sie es wie weiter oben beschrieben aus dem GAC abrufen. Alternativ können Sie alle erforderlichen Assemblys abrufen, indem Sie das Visual Studio 2012 SDK (bit.ly/2rnGsfq) installieren, das diese in den Unterordnern „v2.0“ und „v4.0“ des Ordners „C:\Programme (x86)\Microsoft Visual Studio 11.0\VSSDK\VisualStudioIntegration\Common\Assemblies“ bereitstellt. Die letzte Spalte der Tabelle zeigt den Unterordner des Visual Studio 2012 SDK, in dem Sie die einzelnen Assemblys finden.
Damit Abhängigkeiten von inoffiziellen NuGet-Paketen oder bestimmten lokalen Ordnern (aus einem Visual Studio SDK oder aus einer Visual Studio-Installation) vermieden werden, besteht die beste Vorgehensweise im Abrufen der Assemblys und Erstellen eines Ordners namens „VS2012Assemblies“ unter dem Stammordner des Projekts. Kopieren Sie die DLLs dann in diesen Ordner, verweisen Sie von dort auf sie (mithilfe der Schaltfläche „Durchsuchen“ des Dialogfelds „Verweis-Manager“ des Projekts), und fügen Sie den Ordner „VS2012Assemblies“ der Quellcodeverwaltung hinzu. Stellen Sie dabei sicher, dass die DLLs hinzugefügt werden (normalerweise fügen Tools zur Quellcodeverwaltung DLLs nicht standardmäßig hinzu). Ab jetzt sind die erforderlichen Visual Studio-Assemblys Bestandteil des Quellcodes.
Gemäß dem Prinzip, keine Assemblyverweise in die VSIX-Datei und auch nicht in den Ausgabeordner einzuschließen, wählen Sie jeden Verweis aus und stellen dann im Fenster „Eigenschaften“ sicher, dass die Eigenschaft „Lokale Kopie“ auf FALSE festgelegt ist. Nun kann die Projektmappe ohne Fehler erneut erstellt werden. Navigieren Sie in Windows-Explorer zum Ausgabeordner. Nur diese Dateien sollten generiert werden: „extension.vsixmanifest“, „VSIXProjectVS2012_2017.dll“, „VSIXProjectVS2012_2017.pkgdef“ und „VSIXProjectVS2012_2017.vsix“.
Wenn Sie das Projekt erstellen, stellt eines der MSBuild-Ziele die Erweiterung in der experimentellen Instanz von Visual Studio bereit. Dabei handelt es sich um eine Instanz von Visual Studio, die andere Ordner und Registrierungseinträge als die normale Instanz verwendet, damit die normale Instanz nicht unbrauchbar wird, wenn während der Entwicklung Ihrer Erweiterung ein Fehler auftritt. (Sie können die experimentelle Instanz immer zurücksetzen, indem Sie auf die Windows-Schaltfläche „Start“ klicken, „Reset the“ eingeben und dann den Befehl „Reset the Visual Studio 2017 Experimental Instance“ ausführen.) Wenn Sie auf der Seite „Eigenschaften“ des Projekts auf die Registerkarte „Debuggen“ navigieren, können Sie das Feld „Externes Programm starten“ auf die Datei „devenv.exe“ von Visual Studio 2017 festlegen. (Es ist wichtig, diese Angabe zu ändern, wenn ein Upgrade ausgeführt wird, weil ansonsten auf eine alte Version von Visual Studio verwiesen würde.) Sie können außerdem erkennen, dass die Befehlszeilenargumente „Exp“ als Stammsuffix angeben (siehe Abbildung 8: Debuggen der experimentellen Instanz), damit die experimentelle Instanz auch zum Debuggen verwendet wird.
Abbildung 8: Debuggen der experimentellen Instanz
Klicken Sie auf den Menüeintrag „Debuggen“ > „Debuggen starten“. Es wird eine neue Visual Studio-Instanz gestartet (beachten Sie, dass im Titel „Experimentelle Instanz“ angegeben wird). Wenn Sie auf den Menüeintrag „Extras“ > „MyCommand1 aufrufen“ klicken, wird das Paket geladen, der Befehl wird ausgeführt, und es wird ein Meldungsfeld angezeigt.
Wenn Sie Visual Studio 2017 zum Debuggen der Erweiterung für eine frühere Visual Studio-Version verwenden möchten, müssen Sie zwei Änderungen vornehmen: Da die Erweiterung nach ihrer Erstellung in der experimentellen Visual Studio-Instanz der Version bereitgestellt wird, deren SDK zum Erstellen des Projekts verwendet wurde, müssen Sie zunächst das NuGet-Paket „Microsoft.VSSDK.BuildTools“ (Version 15.0) entfernen und dann Version 14.0 für Visual Studio 2015 oder Version 12.0 für Visual Studio 2013 verwenden. Für Visual Studio 2012 ist kein NuGet-Paket für das VSDK verfügbar. Daher müssen Sie die CSPROJ-Datei bearbeiten und die VSToolsPath-Variable auf den Speicherort des VSSDK 11.0 („C:\Programme (x86)\MSBuild\Microsoft\VisualStudio\v11.0“) verweisen, das Sie separat installieren müssen. Anschließend müssen Sie auf die Registerkarte „Debuggen“ auf der Seite „Eigenschaften“ des Projekts navigieren und das Feld „Externes Programm starten“ auf die entsprechende ausführbare Datei „Common7\IDE\devenv.exe“ festlegen.
Wie Sie vielleicht wissen, unterstützen viele Visual Studio-Projekte Roundtrips. Dies bedeutet, dass sie in mehreren Versionen von Visual Studio ohne Änderungen geöffnet und debuggt werden können. Dies trifft allerdings nicht auf Erweiterbarkeitsprojekte zu, die „out of the box“ verwendet werden. Wenn Sie ausreichende Kenntnisse zu MSBuild und den Visual Studio SDKs besitzen, können Sie ggf. solche Roundtrips erreichen, aber das ist immer ein heikler Ansatz.
Sobald Sie die Entwicklung und das Debuggen abgeschlossen haben, können Sie Ihre Erweiterung in der Releasekonfiguration erstellen und mit den Visual Studio-Versionen testen, die in isolierten Instanzen auf Testcomputern installiert sind. Wenn alles ordnungsgemäß funktioniert, können Sie Ihre Erweiterung anschließend in Visual Studio Marketplace veröffentlichen!
Carlos Quintero wurde bereits 14 Mal als „Microsoft Most Valuable Professional“ ausgezeichnet, zurzeit in der Kategorie „Visual Studio and Development Technologies“. Er unterstützt seit 2002 andere Entwickler beim Erstellen von Erweiterungen für Visual Studio, betreibt seit 2006 unter visualstudioextensibility.com einen Blog zu diesem Thema und ist aktuell auch auf Twitter aktiv: @VSExtensibility.
Unser Dank gilt den folgenden technischen Experten für die Durchsicht dieses Artikels: Justin Clareburt, Alex Eyler und Mads Kristensen