Custom Windows Forms Controls und die ToolBox. Spass beiseite...

Wer schon einmal ein eigenes Control entwickelt hat, kennt die Situation eventuell: Wie bekomme ich das Control sauber in die ToolBox?

Wer sogar in einem Team arbeitet fragt sich mitunter auch: Wie verteile ich meine Controls an mein Team?

Gleich vorweg: Dieser Blogpost behandelt das Problem, dass es mit dem Visual Studio 2010 SP1 SDK unmöglich erscheint, VSIX-Pakete mit ToolBox Controls für .NET 3.5 Projekte zu erstellen (oder besser: Projekte, die auf eine Runtime früher als .NET 4.0 setzen).1

Das Intro nimmt es bereits vorweg: Ein mögliches Werkzeug, um Controls zu verteilen, nennt sich VSIX. Dabei handelt es sich um ein Paketformat von Microsoft, das im Prinzip nichts weiter ist, als eine ZIP komprimierte Datei deren Inhalt sich neben den zu verteilenden Assemblies auch aus Konfigurations- und Metadaten zusammensetzt. Am meisten hat der Entwickler natürlich Spass an solchen Daten, wenn es dafür eine Konfigurationsoberfläche gibt. Und die gibt es tatsächlich!

Sobald das Visual Studio 2010 SP1 SDK installiert ist, findet sich in der Liste angebotener Templates beim Erstellen eines neuen Projektes unter dem Punkt "Extensibility" u.a. das Windows Forms ToolBox Control Projekttemplate. Obacht: Natürlich nur, wenn in der ComboBox das .NET 4.0 Framework ausgewählt ist.

Im Microsoft Developer Network findet sich ein hervorragendes Walkthrough, das die Arbeit mit dem Template erklärt. Insofern gibt es keinen Grund auf diesen Aspekt hier näher einzugehen.

Besonders spannend dabei ist die Möglichkeit, in dem Konfigurationsdialog für das VSIX-Paket anzugeben, für welche minimale und welche maximale Framework-Version das Paket zur Verfügung stehen soll. Die Frage, die sich nämlich aufdrängt ist diese: Wird dort z.B. als minimale Version .NET 3.5 angegeben, wie sollen die Controls dann in einem Projekt eingesetzt werden können, wenn das VSIX-Paket mit dem .NET Framework 4.0 kompiliert wird? Antwort: Gar nicht.

Und hier der Grund für das Dilemma:

Das Projekttemplate importiert das Target-File Microsoft.VsSDK.targets aus dem MSBuild-Verzeichnis unter %ProgramFiles%\MSBuild\Microsoft\VisualStudio\v10.0\VSSDK. Diese Datei referenziert die Assembly Microsoft.VsSDK.Build.Tasks.dll, die u.a. für das Ausführen des Tools CreatePkgDef.exe verantwortlich ist. Dieses Tool analysiert die Assembly, die mit dem Template gebaut wurde, und sucht dabei u.a. nach Klassen, die mit dem RegistrationAttribute dekoriert wurden. Hier drin stecken Metainformationen, die z.B. die ToolBox-Gruppe definieren, in die die jeweiligen Controls gelegt werden sollen.

Das Template beherbergt dazu das ProvideToolboxControlAttribute, welches sich vom RegistrationAttribute ableitet. Dessen Herkunft liegt in der Assembly Microsoft.VisualStudio.Shell, die in verschiedenen Versionen vorliegt. Und hier liegt der Hund begraben. Das Template referenziert dafür die Datei Microsoft.VisualStudio.Shell.Immutable.10.0.dll aus dem Verzeichnis %ProgramFiles%\Microsoft Visual Studio 2010 SDK SP1\VisualStudioIntegration\Common\Assemblies\v4.0. Das Tool CreatePkgDef.exe wurde mit der gleichen Version kompiliert. Ändert man also in seinem Projekt die Runtime auf .NET 3.5 und ersetzt die Referenz durch die Assembly Microsoft.VisualStudio.Shell.dll aus dem ...\2.0 Verzeichnis, lässt sich der Code zwar kompilieren, aber sobald MSBuild CreatePkgDef ausführt, quittiert dieses das Bemühen mit folgender Fehlermeldung:

The assembly should contain an instance of the attribute 'Microsoft.VisualStudio.Shell.RegistrationAttribute' defined in assembly 'Microsoft.VisualStudio.Shell.Immutable.10.0' version '10.0.0.0'

So bringt das keinen Spass!

Der Blick in den Code des RegistrationAttribute (freundlicherweise liefert Microsoft den im SDK mit) zeigt schnell: Das Attribut selbst hat keine weiteren nennenswerten Abhängigkeiten.

Daher funktioniert tatsächlich folgendes Vorgehen:

  1. Aufsetzen eines neuen (Consolen-) Projektes
  2. Dekompilieren der CreatePkgDef.exe2 (z.B. mit JetBrains dotPeek)
  3. Überführen des Quellcodes in das neue Projekt
  4. Referenzieren der Microsoft.VisualStudio.Shell.dll aus dem 2.0'er Zweig des SDKs
  5. Kompilieren
  6. Ersetzen der Original CreatePkgDef.exe im Verzeichnis %ProgramFiles%\Microsoft Visual Studio 2010 SDK SP1\VisualStudioIntegration\Tools\Bin durch die eigene (vorher ein Backup erstellen!)

 

PWNED!

Hier zeigt sich, dass Microsoft sehr nachlässig war. Es erschließt sich leider nicht einmal im Ansatz, warum das Visual Studio SDK neben den 4.0'er Assemblies zwar auch 2.0'er Versionen mitliefert, aber keine Tools, die mit diesen funktionieren. Das hier beschriebene Vorgehen zeigt indes eindeutig, dass es keinen (vernünftigen) Grund gibt, warum das Windows Forms ToolBox Control Template nicht auch mit .NET 3.5 funktionieren sollte.

 

1 Natürlich hindert einen niemand daran, manuell ein VSIX-Paket zu erstellen. Wie gesagt: Es ist eigentlich nur eine ZIP-Datei mit zusätzlichen Informationen.

2 Microsoft hat keinen Obfuscator bei CreatePkgDef.exe eingesetzt, was das Vorgehen im Prinzip sehr einfach gestaltet.

Comments are closed

Über die Autoren

Christian Jacob ist Leiter des Geschäftsbereiches Softwarearchitektur und -entwicklung und zieht als Trainer im Kontext der .NET Entwicklung sowie ALM-Themen Projekte auf links.

Marcus Jacob fokussiert sich auf die Entwicklung von Office-Addins sowie Windows Phone Apps und gilt bei uns als der Bezwinger von Windows Installer Xml.

Martin Kratsch engagiert sich für das Thema Projektmanagement mit dem Team Foundation Server und bringt mit seinen Java- und iOS-Kenntnissen Farbe in unser ansonsten von .NET geprägtes Team.

Aktuelle Kommentare

Comment RSS