COM-Add-Ins sind Erweiterungen für Office-Anwendungen und ihre Entwicklungsumgebung, den VBA-Editor. Damit lassen sich Erweiterungen programmieren, die über die Benutzeroberfläche der jeweiligen Anwendung verfügbar gemacht werden und ihre Aufgabe mit oder ohne ein eigenes User Interface bereitstellen. COM-Add-Ins kann man jedoch nicht mit den Mitteln der Office-Anwendungen selbst programmieren. Dazu sind weitere Tools notwendig. Früher ging dies am einfachsten mit Visual Studio 6. Dieses ist jedoch spätestens seit der Einführung der 64-Bit-Versionen der Office-Anwendungen nicht mehr nutzbar, sodass Alternativen gefragt sind. Neben Visual Studio .NET, das ebenfalls das Erstellen von COM-Add-Ins erlaubt, erschien vor kurzer Zeit eine neue Alternative: twinBASIC. Ein Projekt von Wayne Phillips, das sich nicht nur anschickt, Nachfolger von Visual Studio 6 zu werden, sondern schon jetzt das Erstellen unter anderem von COM-Add-Ins ermöglicht. Dieser Artikel stellt die grundlegenden Techniken zum Erstellen eines Gerüsts für COM-Add-Ins vor, das wir in weiteren Artikeln mit praktischen Lösungen für die Erweiterung der Office-Anwendungen und auch des VBA-Editors nutzen werden.
Vorbereitungen
Wie wir twinBASIC herunterladen und betriebsbereit machen, beschreiben wir im Artikel twinBASIC: Visual Basic für die Zukunft (www.vbentwickler.de/310).
Nach dem Start von twinBASIC finden wir auf der zweiten Seite des Startdialogs namens Samples einige Beispielprojekte vor.
Erstellen eines COM-Add-In-Projekts
Wir starten mit einer der praktischen Vorlagen für die Erstellung verschiedener Beispielprojekte, in diesem Fall Sample 5. MyCOMAddIn (siehe Bild 1).
Bild 1: Erstellen eines COM-Add-Ins auf Basis des passenden Beispiels
Ein Klick auf diese Schaltfläche erstellt ein neues Projekt, das zu diesem Zeitpunkt jedoch noch nicht gespeichert ist. Um dieses zu speichern, betätigen wir den Menübefehl File|Save Project. Dies öffnet, da das Projekt noch ungespeichert ist, einen Save Project As…-Dialog. Mit diesem navigieren wir zu dem gewünschten Zielordner und geben den Dateinamen für das Projekt ein, der die Dateiendung .twinproj trägt (siehe Bild 2).
Bild 2: Festlegen des Speicherorts für die .twinproj-Datei
Schauen wir dann in das Verzeichnis, in dem wir das neue Projekt angelegt haben, stellen wir fest, dass hier tatsächlich nur eine Datei vorliegt – es gibt aktuell noch keine weiteren Elemente.
Damit kehren wir zurück zur twinBASIC-Entwicklungsumgebung, die das neu erstellte Projekt anzeigt.
Module des Beispielprojekts
Das Projekt enthält zu diesem Zeitpunkt zwei Module:
- Das erste heißt MyCOMAddin.twin und wird direkt beim Start im zentralen Bereich der Entwicklungsumgebung angezeigt. Es enthält im Falle eines COM-Add-Ins den gesamten Code des Projekts. Wir schauen uns diesen weiter unten an.
- Das zweite ist das Modul DllRegistration.twin. Dieses enthält Informationen, die erstens beim Erstellen des Projekts zum Testen in die Registry geschrieben werden und die auch beim manuellen Registrieren mit RegSvr32.exe verwendet werden. Auch den Inhalt dieses Moduls schauen wir uns gleich im Detail an.
Für welche Anwendung soll das COM-Add-In eingesetzt werden?
Die wichtigste Frage, die wir beantworten müssen, bevor wir das Add-In überhaupt testweise erstellen, ist die nach der Anwendung, in der das Add-In seine Funktionen zur Verfügung stellen soll.
Aktuell gehen wir davon aus, dass es sich dabei um eine der folgenden Office-Anwendungen handelt:
- Access
- Excel
- Outlook
- PowerPoint
- Word
Oder wollen wir das COM-Add-In sogar für mehrere Office-Anwendungen gleichzeitig verfügbar machen? Das ist möglich, aber es stellt sich die Frage, ob es Anwendungsfälle gibt, die in allen Office-Anwendungen nützlich sind. Tatsächlich gehen wir davon aus, dass ein COM-Add-In eher auf eine Office-Anwendung spezialisiert ist. Dennoch zeigen wir, wie wir das COM-Add-In für mehrere Office-Anwendungen gleichzeitig bereitstellen können.
Soll das COM-Add-In für eine 32-Bit- oder für eine 64-Bit-Anwendung kompiliert werden?
Die zweite Frage, die sich stellt, ist die nach der Architektur der Office-Installation: Ist diese für 32-Bit- oder für 64-Bit ausgelegt? Wir befinden uns in einem Wandel, denn bis vor kurzer Zeit hat das Office-Setup standardmäßig die 32-Bit-Version von Office installiert. Mit Office 2016 und den entsprechenden Versionen unter Office 365 hat sich dies jedoch geändert. Hier landet nun standardmäßig die 64-Bit-Version auf dem Rechner.
Das Problem ist nun, dass auch COM-Add-Ins für die entsprechende Version, also 32-Bit oder 64-Bit, kompiliert werden müssen. Unter twinBASIC ist das ein kleines Problem, wenn auch mit gewissen Einschränkungen. Wir können zwar die entsprechende Zielversion (win32 oder win64) vor der Kompilierung auswählen. Allerdings ist twinBASIC nur für die 32-Bit-Version kostenlos. Wenn wir die 64-Bit-Version kompilieren, wird sowohl während der Kompilierung als auch bei Start des COM-Add-Ins jeweils ein Dialog des Herstellers mit dem twinBASIC-Logo eingeblendet.
Für Entwicklungszwecke und zum Ausprobieren ist das kein Problem. Wir gehen jedoch davon aus, dass wir, wenn wir mit twinBASIC erstellte Anwendungen beim Kunden einsetzen wollen, auch die anfallenden (überschaubaren) Lizenzgebühren gerne entrichten.
Schnellstart mit dem Beispiel-COM-Add-In
Wir wollen direkt einmal das vorgefertigte Beispiel ausprobieren und klicken nach der Auswahl der Zielversion (32-Bit oder 64-Bit) direkt auf die Schaltfläche Build in der Menüleiste (siehe Bild 3).
Bild 3: Erstellen des COM-Add-Ins
Danach können wir das COM-Add-In in Excel und auch in Access ausprobieren. Wenn wir Excel öffnen, finden wir die Möglichkeit zum Aufrufen der Funktion des COM-Add-Ins im Ribbon unter twinBASIC Test. Ein Klick auf die in diesem Tab enthaltene Schaltfläche zeigt ein Meldungsfenster an (siehe Bild 4).
Bild 4: Aufruf des COM-Add-Ins von Excel aus
Das gleiche Ergebnis erhalten wir mit diesem COM-Add-In auch, wenn wir Access öffnen.
Anpassung der Zielanwendung
Der erste Schritt der Anpassung des COM-Add-Ins soll sich auf die Anwendung beziehen, in welcher dieses angezeigt wird. Diese Einstellung nehmen wir im Modul DllRegistration vor.
Hier finden wir den Code aus Listing 1. Wir sehen ganz oben, dass unter twinBASIC Standardmodule in Module [Modulname] und End Module eingefasst werden müssen. Wir sehen außerdem einige Konstanten, welche Informationen enthalten, die in den beiden weiter unten definierten Funktionen zum Einsatz kommen. Die erste speichert den Namen des Projekts, der aus VBA.Compilation.CurrentProjectName bezogen wird. Die Klasse Compilation ist eine twinBASIC-Erweiterung, die Informationen über das aktuelle Projekt liefert und deren Member wir beispielsweise wie in Bild 5 per IntelliSense abfragen können. In diesem Fall ermitteln wir den aktuellen Projektnamen. Wie wir den Projektnamen anpassen, zeigen wir weiter unten.
Bild 5: Die Compilation-Klasse per IntelliSense
Die zweite Konstante namens AddinClassName erhält den Namen der Klasse des Add-Ins. Dieser sollte mit dem Namen der Klasse im anderen Modul des Projekts übereinstimmen, in diesem Fall MyCOMAddin. Die nächste Konstante AddinQualifiedClassName fügt die beiden vorher definierten Konstanten, also AddinProjectName und AddinClassName zusammen.
Schließlich folgen noch zwei Konstanten namens RootRegistryFolder_ACCESS und RootRegistryFolder_EXCEL, welche die Pfade zu den zu erstellenden Einträgen für das COM-Add-In in der Registry aufnehmen. Für Access entsteht so beispielsweise der folgende Wert für diese Konstante:
HKCU\SOFTWARE\Microsoft\Office\Access\Addins\MyCOMAddin.MyCOMAddin\
Wozu Registry-Einträge?
Warum machen wir in Zusammenhang mit der Installation eines COM-Add-Ins überhaupt so einen Wirbel um Registry-Einträge? Der Grund ist einfach: Die Office-Anwendungen scannen beim Starten einen bestimmten Bereich der Registry, wo die für die jeweilige Anwendung registrierten COM-Add-Ins aufgelistet werden. Die dort angegebenen DLLs werden beim Start der Anwendung ausgelesen und dort untergebrachte Schnittstellen für die Anpassung von Ribbondefinitionen angewendet.
Um zu prüfen, ob das soeben erstellte COM-Add-In seinen Platz in der Registry gefunden hat, brauchen wir eigentlich nicht die Registry zu öffnen, denn wir haben uns ja durch Starten der Anwendungen Access und Excel davon überzeugt, dass das COM-Add-In für die beiden Anwendungen installiert ist.
Dennoch schauen wir uns die Registry an, wobei wir diese mit dem Befehl RegEdit über das Suchen-Feld von Windows öffnen.
Hier navigieren wir zum folgenden Eintrag:
Computer\HKEY_CURRENT_USER\SOFTWARE\Microsoft\Office\Excel\Addins\MyCOMAddin.MyCOMAddin
Dies ist beispielsweise der Eintrag für Excel. Für diesen wurden einige Werte hinterlegt (siehe Bild 6).
Bild 6: Das Add-In für Excel in der Registry
Diese haben die folgende Bedeutung:
- Description: Beschreibung, die beispielsweise im Bereich Add-Ins der Optionen der jeweiligen Anwendung auftaucht
- FriendlyName: Name des COM-Add-Ins, wie er in der Liste der COM-Add-Ins im Dialog COM-Add-Ins auftaucht
- LoadBehaviour: Verhalten beim Laden. Normalerweise soll hier der Wert 3 stehen für Beim Start Laden. Diesen Wert sehen wir ebenfalls im Dialog COM-Add-Ins.
Die Werte für FriendlyName und Description sowie den Speicherort der DLL finden wir nach der Installation des COM-Add-Ins beispielsweise für Excel im Optionen-Dialog im Bereich Add-Ins.
Die einzelnen Werte haben wir in Bild 7 hervorgehoben.
Bild 7: COM-Add-Ins in den Excel-Optionen
Wählen wir hier im unteren Bereich für das Kombinationsfeld Verwalten den Wert COM-Add-Ins aus und klicken auf die Schaltfläche Los…, finden wir den Dialog aus Bild 8 vor. Hier sehen wir auch den aktuellen Wert für die Eigenschaft Ladeverhalten, in diesem Fall Beim Start laden.
Bild 8: Der Dialog COM-Add-Ins
Funktion zum Einrichten der Registry-Einträge
Nachdem wir uns nun mit der Bedeutung des Vorhandenseins gewisser Registry-Einträge beschäftigt haben, wollen wir uns ansehen, wie diese dorthin gelangen.
Diese Aufgabe übernimmt die Funktion DllRegisterServer im Modul DllRegistration. Diese Funktion erzeugt eine Instanz des Objekt wscript.shell, welches beispielsweise die Methode RegWrite zum Schreiben von Registry-Einträgen bereitstellt. Diese nutzen wir, um die benötigten Einträge mit den Werten, die teilweise aus den oben definierten Konstanten stammen, zur Registry hinzuzufügen.
Das alles geschieht unter Deaktivierung der eingebauten Fehlerbehandlung mit On Error Goto RegError. Tritt beim Anlegen der Registry-Einträge ein Fehler auf, zeigt die Funktion ein Meldungsfenster mit Details zum aufgetretenen Fehler an.
Wann wird DllRegisterServer aufgerufen?
Es gibt zwei Gelegenheiten, zu denen die Funktion DllRegister aufgerufen wird. Die erste ist das Betätigen der Build-Schaltfläche in der twinBASIC-Entwicklungsumgebung.
Ob sie dadurch tatsächlich aufgerufen wird, können wir anschließend am Vorhandensein der dort definierten Registry-Einträge feststellen. Wir können aber auch einfach eine MsgBox-Anweisung einbauen und uns beispielsweise den Pfad in der Registry ausgeben lassen, in welchen die Registry-Informationen geschrieben werden.
Der zweite Zeitpunkt, zu dem diese Funktion aufgerufen wird, ist die Registrierung auf dem jeweiligen Zielrechner mit der Anweisung RegSvr32.exe entweder über die Eingabeaufforderung oder auch per Batch-Datei.
Wenn wir die COM-Add-In-Datei also auf einen anderen Rechner kopiert haben und diese installieren wollen, müssen wir diese mehr oder weniger von Hand registrieren, wenn wir nicht gerade ein Setup für das COM-Add-In erstellt haben. Wie wir ein solches Setup erstellen, erläutern wir noch in einem weiteren Beitrag.
Über die Eingabeaufforderung gelingt das wie folgt:
- Als Erstes starten wir die Eingabeaufforderung, und zwar im Administrator-Modus. Dazu geben wir im Suchen-Feld von Windows den Text cmd ein und klicken dann mit der rechten Maustaste auf den nun im Suchergebnis erscheinenden Eintrag Eingabeaufforderung. Im Kontextmenü wählen wir Als Administrator ausführen aus.
- Danach navigieren wir zu dem Verzeichnis, in dem sich die .dll-Datei befindet, in diesem Fall auf dem Desktop.
- Hier geben wir den Befehl Regsvr32.exe MyCOMAddin_win64.dll ein.
- Hier erhalten wir dann im Optimalfall die Meldung, dass die DLL erfolgreich registriert wurde (siehe Bild 9).
Bild 9: Installieren per Eingabeaufforderung
Wir sehen, dass wir die twinBASIC-Funktion DllRegisterServer auch von der Kommandozeile aus aufrufen können. Das eröffnet uns auch die Möglichkeit, dort weitere Mechanismen unterzubringen, die für die Verwendung des COM-Add-Ins noch hilfreich sein können – beispielsweise das Anlegen bestimmter Dateien mit Konfigurationsdateien, die Anzeige von Meldungen während der Installation et cetera.
Den Befehl Regsvr32.exe können wir in eine Batch-Datei schreiben und diese dann im Administratormodus aufrufen. Diese Datei nennen wir einfach Register.bat. Wenn wir diese Datei im gleichen Verzeichnis platzieren wie die zu registrierende Datei, brauchen wir noch nicht mal den Pfad zur zu registrierenden .dll-Datei anzugeben, wie es eigentlich nötig wäre, wenn wir nicht in der Eingabeaufforderung zum Verzeichnis mit der .dll-Datei navigiert hätten.
Funktion zum Entfernen der Registry-Einträge
Wenn wir ein Element durch Hinzufügen von Einträgen zur Registry installieren, wollen wir dieses auch wieder deinstallieren können. Dazu können wir die Funktion DllUnregisterServer nutzen. Der Aufbau dieser Funktion ist dem der Prozedur zum Hinzufügen der Registry-Einträge recht ähnlich. Allerdings nutzen wir hier nicht die Methode RegWrite der Klasse wscript.shell, sondern die Methode RegDelete.
Hier sind nicht nur drei Aufrufe nötig, sondern noch ein weiterer. Beim Registrieren werden nämlich automatisch alle Ordner angelegt, die zu den hinzuzufügenden Registry-Einträgen führen – in diesem Fall der Ordner aus der Konstanten AddinQualifiedClassName. Den so angelegten Ordner müssen wir beim Deinstallieren nach dem Löschen der eigentlichen Registry-Einträge separat wieder entfernen.
Der Rest läuft wie beim Anlegen der Registry-Einträge ab.
Wenn wir die Registrierung auf dem Zielrechner wieder aufheben wollen, können wir wie beim Registrieren vorgehen – wir rufen in der für den Administratorzugriff geöffneten Eingabeaufforderung den gleichen Befehl auf, diesmal allerdings mit dem Parameter -u:
Regsvr32 MyCOMAddin_win32.dll -u
Bedingungen für das Registrieren und Deregistrieren von COM-Add-Ins
Wenn wir ein COM-Add-In für eine Anwendung registrieren, können wir dies unabhängig davon erledigen, ob die Zielanwendung aktuell geöffnet ist oder nicht. Die einzige Konsequenz, wenn die Anwendung geöffnet ist, ist folgende: Das COM-Add-In ist dann nicht sofort, sondern erst beim nächsten Öffnen der Anwendung verfügbar.
Beim Registrieren im Rahmen des Erstellens des COM-Add-Ins von der twinBASIC-Entwicklungsumgebung aus sollten wir die Zielanwendungen jedoch immer schließen. Ansonsten kann es vorkommen, dass beim Versuch, die bestehende Version der .dll-Datei zu löschen und diese neu zu erstellen, ein Fehler auftritt, weil die .dll-Datei gerade in Verwendung ist.
Modul DLLRegistration auf die Zielanwendung anpassen
Wenn wir entschieden haben, für welche Anwendung das COM-Add-In zum Einsatz kommen soll, können wir die beiden Funktionen DllRegister und DllUnregister entsprechend anpassen. Wir können dann zuerst einen Satz von Registry-Informationen entfernen. Dann passen wir die Funktionen wie folgt an. Die Funktion DLLRegister sieht dann wie in Listing 2 aus.
Public Function DllRegisterServer() As Boolean On Error GoTo RegError Dim wscript As Object = CreateObject("wscript.shell") wscript.RegWrite RootRegistryFolder & "FriendlyName", AddinProjectName + "_Friendly", "REG_SZ" wscript.RegWrite RootRegistryFolder "Description", AddinProjectName + "_Description", "REG_SZ" wscript.RegWrite RootRegistryFolder & "LoadBehavior", 3, "REG_DWORD" Return True RegError: MsgBox "DllRegisterServer -- An error occured trying to write to the system registry:" & vbCrLf & _ Err.Description & " (" & Hex(Err.Number) & ")" Return False End Function
Möchten Sie weiterlesen? Dann lösen Sie Ihr Ticket!
Hier geht es zur Bestellung des Jahresabonnements des Magazins Visual Basic Entwickler:
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:
Hallo, im vorhergehenden Beitrag (“twinBASIC – VB für die Zukunft”) ist die u.a. Rede von …
ActiveX Control
ActiveX DLL,
deren Entwicklung alle mit twinBASIC möglich sei.
Hier im (nächsten) Beitrag wird dann aber von mit twinBASIC zu erstellenden “COM-Add-Ins” gesprochen, von denen ebenfalls in einem weiteren Beitrag “COM-DLL für den Zugriff auf die YouTube-API” , dann aber im Zusammenhang mit VB.NET, die Rede ist.
Meines Erachtens gehen da die Begriffe ein wenig durcheinander bzw werden nicht erläutert. Möglicherweise sind “COM-.DLLs” als Oberbegriff verwendet worden. Aber warum wird dann später für YouTube auf Basis von VB.NET(!) eine COM-DLL entwickelt, wo es doch heißt, dass das mit dem revolutionären “twinBASIC” jetzt ebenso funktioniert!? Zumindest sollte diskutiert werden, ob das VB.NET-Projekt tatsächlich auch mit twinBASUC realisiert werden kann – oder wo die eventuellen Haken bzw Unterschiede liegen …
Danke!
Die Antwort ist einfach: Für .NET gibt es viel mehr Bibliotheken, die man beispielsweise per NuGet in eine damit erzeugte COM-DLL oder in ein COM-Add-In einfügen kann. Bei twinBASIC kann man in COM-DLLs oder COM-Add-Ins nur andere COM-Quellen einbinden, aber nicht beispielsweise NuGet-Elemente. Daher entscheide ich beispielsweise, ob ich mit den “Bordmitteln” von VB6 auskomme und mache dann eine twinBASIC-COM-DLL oder -COM-Add-In. Wenn Schnittstellen wie beispielsweise für Youtube oder andere moderne Tools nötig sind, dann mache in eine .NET-DLL.