.NET 8-DLL typisiert aus VBA verwenden - COM-Freigabe und dscom-TLB

· · C#, .NET 8, VBA, COM, Office, dscom

Es gibt nach wie vor ganz normale Situationen, in denen Sie aus VBA heraus .NET 8-Code aufrufen möchten. Insbesondere dann, wenn Sie die bestehenden Excel- oder Access-Bestände unverändert erhalten, aber nur Teile wie aufwendige Verarbeitung, Zeichenkettenverarbeitung, HTTP, Verschlüsselung oder Fachlogik nach C# auslagern wollen.

Setzen Sie dabei allerdings mit CreateObject auf späte Bindung, ist die VBA-Seite bald voller Object. IntelliSense wird schwächer, Tippfehler bei Methodennamen fallen erst zur Laufzeit auf, und man versinkt allmählich in einem Sumpf aus reiner Zeichenkettenabhängigkeit.

Deshalb konzentrieren wir uns diesmal darauf, eine .NET 8-DLL als COM freizugeben, mit dscom eine Typbibliothek (TLB) zu erzeugen und sie aus VBA mit früher Bindung (early binding) typisiert zu verwenden.

Die alte Geschichte von .NET Framework + RegAsm, das Handschreiben von IDL mit anschließendem MIDL-Build sowie Reg-Free COM lassen wir diesmal beiseite. Hier behandeln wir ausschließlich den einen Weg .NET 8 / COM-Host / dscom / VBA-frühe Bindung.

Der in diesem Artikel gezeigte Code ist außerdem als vollständiges, build- und überprüfbares Beispielpaket (COM-freigegebene Bibliothek, TLB-Erzeugungs- und Registrierungsskripte, VBA-Module, Unit-Tests) auf GitHub veröffentlicht.

dotnet8-dll-typed-vba-com-dscom-tlb - komurasoft-blog-samples (GitHub)

Benötigte Umgebung

Element Erforderlich
Betriebssystem Windows. Da eine COM-Registrierung erfolgt, müssen Sie regsvr32 mit Administratorrechten ausführen können
.NET SDK .NET 8 SDK. EnableComHosting ist eine Funktion ab .NET 5
Office Excel oder Access. Prüfen Sie zuerst, ob die 32-Bit- oder die 64-Bit-Version vorliegt (Kapitel 3)
TLB-Erzeugungswerkzeug dscom. Die Beschaffung unterscheidet sich für 64-Bit und 32-Bit (Kapitel 6)
Client-PC .NET 8-Laufzeit mit derselben Bitness wie Office (Kapitel 9)

Bevor Sie mit den Schritten beginnen, empfehlen wir dringend, die Versionen Ihrer eigenen Umgebung zu notieren. Wenn später „dieselben Schritte, aber es funktioniert nicht“ auftritt, sind diese Angaben oft die einzige Vergleichsgrundlage.

# Liste der installierten .NET SDKs und Laufzeiten (zeigt auch, ob x64 oder x86 installiert ist)
dotnet --info

# Windows-Buildnummer
winver

Version und Bitness von Office lassen sich in Excel unter Datei > Konto > Info zu Excel prüfen. Am Ende der Titelzeile des Dialogs steht 32-Bit oder 64-Bit.

1. Zuerst das Ergebnis

Fassen wir vorab nur das Ergebnis zusammen, sieht der Ablauf so aus.

  • Die .NET 8-Klassenbibliothek mit EnableComHosting=true bauen
  • Eine explizite Schnittstelle und eine Klasse erstellen, die COM zeigt
  • Die Klasse auf ClassInterfaceType.None setzen und nicht auf AutoDual ausweichen
  • Die aus VBA verwendete Schnittstelle auf InterfaceIsDual setzen
  • Aus der nach dem Build entstandenen *.dll mit dscom tlbexport eine *.tlb erzeugen
  • Die *.comhost.dll mit regsvr32 registrieren
  • Die *.tlb mit dscom tlbregister registrieren
  • In VBA einen Verweis hinzufügen und typisiert verwenden, etwa als Dim x As Bibliotheksname.IYourInterface

Kurz gesagt: Der COM-Einstiegspunkt ist die vom .NET SDK erzeugte *.comhost.dll, die Typinformationen liefert die von dscom erzeugte *.tlb, und VBA bindet anhand dieser TLB früh (early binding).

2. Der Gesamtüberblick dieses Aufbaus

Zunächst sehen wir uns in einem einzigen Diagramm an, was welche Rolle übernimmt.

Typinformationen aus der referenzierten TLBCOM-AufrufVBA / Excel / AccessVbaTypedComSample.tlbVbaTypedComSample.comhost.dllVbaTypedComSample.dll (.NET 8).NET 8 Runtime

Die jeweiligen Rollen sehen so aus.

Datei Rolle
VbaTypedComSample.dll Die eigentliche .NET 8-Implementierung
VbaTypedComSample.comhost.dll Der von COM aufgerufene Einstiegspunkt
VbaTypedComSample.tlb Die Typinformationen, die VBA sieht
VbaTypedComSample.deps.json Informationen zur Auflösung von Abhängigkeiten
VbaTypedComSample.runtimeconfig.json Startinformationen für die .NET-Laufzeit

Wichtig ist hier: Damit VBA die Typen kennt, ist die TLB nötig, und als COM-Starteinstiegspunkt wird der comhost benötigt.

Dass man nicht einfach nur die .dll allein weitergeben und fertig sein kann, ist genau der Punkt, an dem die COM-Welt nicht ganz geradlinig ist.

3. Zuerst entscheiden - 32-Bit / 64-Bit angleichen

Übersehen Sie das, landen Sie mit hoher Wahrscheinlichkeit bei ActiveX-Komponente kann kein Objekt erstellen.

Stellen Sie sicher, dass die Bitness von Office/VBA und dem COM-Server übereinstimmt.

Verwendung Richtwert auf .NET-Seite TLB-Erzeugung Registrierungsbefehl
64-Bit-Office x64 / win-x64 dscom C:\Windows\System32\regsvr32.exe
32-Bit-Office (auf 64-Bit-Windows) x86 / win-x86 dscom32.exe C:\Windows\SysWOW64\regsvr32.exe

Bei einem COM-Host unter .NET 5+ neigt *.comhost.dll dazu, in Richtung 64-Bit zu wandern, wenn Sie bei AnyCPU bleiben, was mit 32-Bit-Office nicht zusammenpasst. Deshalb ist es sicherer, x86 / x64 passend zu Office explizit anzugeben.

Der Code in diesem Artikel verwendet als Beispiel 64-Bit-Office. Bei 32-Bit-Office lesen Sie das später auftauchende x64 als x86 und win-x64 als win-x86.

4. Die .NET 8-Seite erstellen

Hier erstellen wir ein minimales Beispiel, bei dem VBA Add, Divide und Hello aufrufen kann.

4.1 .csproj

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net8.0-windows</TargetFramework>
    <Nullable>enable</Nullable>
    <ImplicitUsings>enable</ImplicitUsings>
    <EnableComHosting>true</EnableComHosting>
    <PlatformTarget>x64</PlatformTarget>
    <NETCoreSdkRuntimeIdentifier>win-x64</NETCoreSdkRuntimeIdentifier>
  </PropertyGroup>
</Project>

Der entscheidende Punkt ist EnableComHosting. Setzen Sie das, wird beim Build VbaTypedComSample.comhost.dll erzeugt.

4.2 Die gesamte Assembly standardmäßig COM-unsichtbar lassen

Da nur die Typen, die Sie COM zeigen wollen, ComVisible(true) erhalten sollen, ist es am einfachsten, die gesamte Assembly auf false zu setzen.

using System.Runtime.InteropServices;

[assembly: ComVisible(false)]

4.3 Die zu veröffentlichende Schnittstelle und Klasse schreiben

using System.Runtime.InteropServices;

namespace VbaTypedComSample;

[ComVisible(true)]
[Guid("2A1BBEDE-DE6E-4C34-AD60-2E9E0E33E999")]
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
public interface ICalculator
{
    [DispId(1)]
    int Add(int x, int y);

    [DispId(2)]
    double Divide(double x, double y);

    [DispId(3)]
    string Hello(string name);
}

[ComVisible(true)]
[Guid("FAD1C752-0BB6-4DDD-889F-FE446350847A")]
[ClassInterface(ClassInterfaceType.None)]
[ComDefaultInterface(typeof(ICalculator))]
public class Calculator : ICalculator
{
    public Calculator()
    {
    }

    public int Add(int x, int y) => checked(x + y);

    public double Divide(double x, double y)
    {
        if (y == 0)
        {
            throw new ArgumentOutOfRangeException(nameof(y), "Division durch 0 ist nicht möglich.");
        }

        return x / y;
    }

    public string Hello(string name)
    {
        if (string.IsNullOrWhiteSpace(name))
        {
            return "Hello";
        }

        return $"Hello, {name}";
    }
}

Bei diesem Code sind folgende Punkte wichtig.

  • Vergeben Sie Guid getrennt für die Schnittstelle und die Klasse
  • Setzen Sie ClassInterfaceType.None, um nicht von der automatisch generierten Klassenschnittstelle abhängig zu sein
  • Setzen Sie InterfaceIsDual, damit sich die Schnittstelle aus VBA leicht handhaben lässt
  • Das Vergeben von DispId verringert Unfälle, wenn Sie nach der Veröffentlichung die Methodenreihenfolge ändern
  • Da COM die Klasse per New erzeugt, stellen Sie einen öffentlichen parameterlosen Konstruktor bereit

5. Bauen

Wir führen einen Release-Build durch.

dotnet build -c Release

Nach dem Build enthält der Ausgabeordner mindestens die folgenden Dateien.

bin/
  Release/
    net8.0-windows/
      VbaTypedComSample.dll
      VbaTypedComSample.comhost.dll
      VbaTypedComSample.deps.json
      VbaTypedComSample.runtimeconfig.json

Für Verteilung und Registrierung verwenden Sie diesen Ordner. Ändern Sie später den Ablageort, müssen Sie auch die Registrierung wiederholen.

6. Die TLB mit dscom erzeugen

6.1 Was ist dscom

dscom ist ein Open-Source-Kommandozeilenwerkzeug, mit dem Sie aus einer .NET-Assembly eine COM-Typbibliothek (TLB) erzeugen und registrieren können. Es wird von der dSPACE GmbH veröffentlicht und steht unter der Apache-2.0-Lizenz.

Der Grund, warum es benötigt wird: Ab .NET 5 wurden tlbexp.exe und RegAsm.exe abgeschafft. In der Zeit von .NET Framework konnten diese beiden Werkzeuge TLBs erzeugen und Assemblys registrieren, doch .NET 5+ bringt standardmäßig keinen Nachfolger dafür mit. dscom wurde geschaffen, um genau diese Lücke zu schließen.

Die wichtigsten Subbefehle reichen aus, wenn Sie sich nur diese merken.

Subbefehl Rolle
tlbexport Schreibt die TLB aus der Assembly heraus
tlbregister Registriert die TLB im System
tlbunregister Hebt die Registrierung der TLB auf
tlbdump Gibt den Inhalt der TLB zur Prüfung aus
tlbembed Bettet die TLB in eine Datei ein

tlbdump eignet sich gut, um vor dem Öffnen von VBA zu prüfen, ob die erzeugte TLB die vorgesehenen Typen enthält.

6.2 Für 64-Bit

Wollen Sie nur eine 64-Bit-TLB erzeugen, genügt die Installation über dotnet tool.

dotnet tool install --global dscom

Als Nächstes erzeugen Sie aus der gebauten Assembly die TLB.

dscom tlbexport .\bin\Release\net8.0-windows\VbaTypedComSample.dll --out .\bin\Release\net8.0-windows\VbaTypedComSample.tlb

6.3 Für 32-Bit-Office - Woher Sie dscom32.exe beziehen

Das ist bei der 32-Bit-Office-Unterstützung die größte Stolperfalle.

Das über dotnet tool install installierte dscom kann nur AnyCPU- oder 64-Bit-Assemblys verarbeiten und lediglich 64-Bit-TLBs erzeugen. Um eine 32-Bit-TLB zu erzeugen, benötigen Sie die separate ausführbare Datei dscom32.exe, die Sie nicht über NuGet, sondern von der GitHub-Releaseseite herunterladen.

Die heruntergeladene dscom32.exe legen wir in den Beispielen dieses Artikels im Ordner tools direkt unter dem Projekt ab. Der Ablageort ist frei wählbar, aber verteilen Sie sie nicht zusammen mit der Build-Ausgabe. Es handelt sich um ein Entwicklungswerkzeug, das zur Laufzeit nicht benötigt wird.

Es gibt noch eine leicht übersehene Voraussetzung: Um dscom32.exe auszuführen, muss die x86-Version der .NET-Laufzeit installiert sein. Das liegt daran, dass dscom hostfxr.dll lädt; in einer Umgebung, in der nur die x64-Version installiert ist, funktioniert es nicht. Prüfen Sie in der Liste der Ausgabe von dotnet --info, ob eine x86-Laufzeit vorhanden ist.

.\tools\dscom32.exe tlbexport .\bin\Release\net8.0-windows\VbaTypedComSample.dll --out .\bin\Release\net8.0-windows\VbaTypedComSample.tlb

Auch in der Dokumentation von dscom selbst wird empfohlen, die Assembly bei 32-Bit-Nutzung direkt für 32-Bit zu kompilieren, da *.comhost.dll bei AnyCPU als 64-Bit erzeugt wird. Das ist dieselbe Schlussfolgerung wie in Kapitel 3.

Wenn es lästig ist, die TLB bei jedem Build manuell zu erzeugen, können Sie das Paket dSPACE.Runtime.InteropServices.BuildTasks einbinden, damit die TLB automatisch beim Kompilieren erzeugt wird.

7. COM-Host und TLB registrieren

Führen Sie dies in einer Eingabeaufforderung / PowerShell mit Administratorrechten aus.

7.1 Für 64-Bit-Office / 64-Bit-COM

$out = Resolve-Path .\bin\Release\net8.0-windows

C:\Windows\System32\regsvr32.exe "$out\VbaTypedComSample.comhost.dll"
dscom tlbregister "$out\VbaTypedComSample.tlb"

7.2 Für 32-Bit-Office (auf 64-Bit-Windows)

$out = Resolve-Path .\bin\Release\net8.0-windows

C:\Windows\SysWOW64\regsvr32.exe "$out\VbaTypedComSample.comhost.dll"
.\tools\dscom32.exe tlbregister "$out\VbaTypedComSample.tlb"

Hier passieren zwei Dinge.

  • regsvr32 registriert *.comhost.dll als COM-Server
  • tlbregister registriert *.tlb als Typbibliothek

8. In VBA einen Verweis hinzufügen und typisiert verwenden

  1. Excel oder Access öffnen
  2. Mit Alt + F11 den VBA-Editor (VBE) öffnen. Über das Menüband öffnen Sie ihn unter Entwicklertools > Visual Basic. Wird die Registerkarte Entwicklertools nicht angezeigt, aktivieren Sie sie unter Datei > Optionen > Menüband anpassen mit dem Häkchen bei Entwicklertools
  3. Im VBE-Menü Extras > Verweise
  4. Die Liste Verfügbare Verweise ist alphabetisch sortiert. War die Registrierung erfolgreich, erscheint dort der Bibliotheksname (standardmäßig identisch mit dem Assemblynamen VbaTypedComSample) – setzen Sie das Häkchen links davon und klicken Sie auf OK
  5. Erscheint er nicht in der Liste, wählen Sie über die Schaltfläche Durchsuchen... direkt VbaTypedComSample.tlb aus

Erscheint sie nicht in der Liste, liegt die Ursache meist entweder an der Bitness-Diskrepanz aus Kapitel 3 oder daran, dass tlbregister aus Kapitel 7 nicht erfolgreich durchgelaufen ist. Aus 32-Bit-Office heraus ist eine mit 64-Bit registrierte TLB nicht sichtbar.

Ob der Verweis gesetzt ist, prüfen Sie, indem Sie Ansicht > Objektkatalog (F2) öffnen und oben links in der Bibliotheksauswahl prüfen, ob sich VbaTypedComSample auswählen lässt. Sehen Sie hier ICalculator und Calculator sowie Add / Divide / Hello, wurde die TLB korrekt erzeugt.

Option Explicit

Public Sub UseCalculator()
    Dim calc As VbaTypedComSample.ICalculator
    Set calc = New VbaTypedComSample.Calculator

    Debug.Print calc.Add(10, 20)
    Debug.Print calc.Divide(10, 4)
    Debug.Print calc.Hello("VBA")
End Sub

Platzieren Sie den Cursor in dieser Prozedur, führen Sie sie mit F5 aus und öffnen Sie mit Ctrl + G das Direktfenster – dann erscheinen entsprechend der Implementierung aus Kapitel 4 drei Zeilen.

30
2.5
Hello, VBA

Stimmt das mit der Erwartung überein, laufen Verweis, COM-Registrierung, Laufzeitstart sowie das Marshalling von Argumenten und Rückgabewerten allesamt korrekt durch. Stimmen die Werte hier nicht, prüfen Sie die .NET-Implementierung; lässt es sich überhaupt nicht ausführen, prüfen Sie Kapitel 3 und Kapitel 7.

Damit ergeben sich für die VBA-Seite folgende Vorteile.

  • IntelliSense funktioniert
  • Tippfehler bei Methodennamen fallen leichter schon vor der Ausführung auf
  • Die veröffentlichte API lässt sich im Objektkatalog einsehen
  • Besser lesbar als das reine Schreiben von Object

8.1 Ausnahmen werden auf der VBA-Seite zu COM-Fehlern

Wird zum Beispiel wie bei Divide(10, 0) auf der .NET-Seite eine Ausnahme ausgelöst, erscheint sie auf der VBA-Seite als COM-Fehler.

Option Explicit

Public Sub UseCalculatorWithErrorHandling()
    On Error GoTo EH

    Dim calc As VbaTypedComSample.ICalculator
    Set calc = New VbaTypedComSample.Calculator

    Debug.Print calc.Divide(10, 0)
    Exit Sub

EH:
    Debug.Print Err.Number
    Debug.Print Hex$(Err.Number)
    Debug.Print Err.Description
End Sub

Wenn Sie wissen, wie die hier ausgegebenen Werte zu lesen sind, geht die Eingrenzung schneller.

Element Was enthalten ist
Err.Number Enthält den zur .NET-Ausnahme gehörenden HRESULT-Wert als vorzeichenbehaftete Long-Zahl. Da er dezimal schwer lesbar ist, wandeln Sie ihn mit Hex$(Err.Number) in eine hexadezimale Darstellung um
Err.Description Enthält über die COM-Schnittstelle IErrorInfo die .NET-Ausnahmemeldung unverändert. Beim obigen Code ist das ein String, der Division durch 0 ist nicht möglich. enthält

Der HRESULT-Wert ist pro Ausnahmetyp festgelegt. ArgumentOutOfRangeException entspricht COR_E_ARGUMENTOUTOFRANGE mit dem Wert 0x80131502. Ist Hex$(Err.Number) also gleich 80131502, bedeutet das, dass wie erwartet die ArgumentOutOfRangeException von der .NET-Seite angekommen ist.

Die wichtigsten im Überblick.

.NET-Ausnahme HRESULT-Konstante Wert
ArgumentException COR_E_ARGUMENT 0x80070057
ArgumentOutOfRangeException COR_E_ARGUMENTOUTOFRANGE 0x80131502
InvalidOperationException COR_E_INVALIDOPERATION 0x80131509
NotSupportedException COR_E_NOTSUPPORTED 0x80131515
Alle übrigen allgemeinen Ausnahmen COR_E_EXCEPTION 0x80131500

Möchten Sie auf der VBA-Seite je nach Ausnahmeart unterschiedlich reagieren, verzweigen Sie anhand dieses HRESULT. Ein Design, das anhand des HRESULT verzweigt, ist jedoch anfällig gegenüber Änderungen der .NET-Ausnahmetypen, weshalb es als Grenzfläche stabiler ist, fachliche Fehlschläge nicht als Ausnahme, sondern über Rückgabewerte oder Fehlercodes zu melden.

9. Überlegungen zur Verteilung

Wichtig bei der Verteilung ist, nicht nur die DLL allein weiterzugeben, sondern die gesamte Ausgabe bereitzustellen.

VbaTypedComSample.dll
VbaTypedComSample.comhost.dll
VbaTypedComSample.deps.json
VbaTypedComSample.runtimeconfig.json
VbaTypedComSample.tlb
(bei Bedarf sämtliche abhängigen DLLs)

Zudem benötigt der Client-PC die passende .NET 8-Laufzeit. Der COM-Host wird grundsätzlich nicht als self-contained, sondern framework-dependent betrieben.

Konkret geht es um Folgendes.

  • Die Downloadseite ist .NET 8 herunterladen
  • Benötigt wird nicht das SDK, sondern die Laufzeit. Da das Beispiel in diesem Artikel eine Klassenbibliothek ohne Oberfläche ist, genügt .NET Runtime. Verwenden Sie Typen aus WPF oder Windows Forms, benötigen Sie .NET Desktop Runtime
  • Die Bitness richtet sich nach Office. Bei 64-Bit-Office ist es die x64-Laufzeit, bei 32-Bit-Office die x86-Laufzeit. Aus demselben Grund, aus dem in Kapitel 3 x64 / x86 explizit angegeben wurde, startet auch hier nichts, wenn es nicht übereinstimmt
  • Ob sie bereits installiert ist, sehen Sie, indem Sie auf dem Client-PC dotnet --list-runtimes ausführen und prüfen, ob eine Zeile mit Microsoft.NETCore.App 8.x erscheint

Halten Sie in der Verteilungsdokumentation unbedingt diese Angaben fest – „erforderliche Art, Version und Bitness der Laufzeit“. Vergessen Sie das in der Installationsanleitung, sieht man vor Ort ActiveX-Komponente kann kein Objekt erstellen., vermutet eine Bitness-Diskrepanz und verschwendet Zeit.

10. Stolperfallen

10.1 AnyCPU nicht unverändert belassen

Weichen die Bitness von VBA/Office und die des COM-Hosts voneinander ab, kommt es zu ziemlich unangenehmen Fehlschlägen.

  • Bei 64-Bit-Office: x64 / win-x64
  • Bei 32-Bit-Office: x86 / win-x86

10.2 ClassInterfaceType.AutoDual nicht verwenden

Es wirkt zunächst bequem, bricht aber leicht, sobald Sie nach der Veröffentlichung Reihenfolge oder Zusammensetzung der Member ändern.

Wenn Sie stabil typisiert aus VBA arbeiten möchten, ist es bewährte Praxis, eine explizite Schnittstelle zu definieren und die Klasse auf ClassInterfaceType.None zu setzen.

10.3 GUIDs nicht leichtfertig neu erzeugen

In COM ist die GUID selbst der Vertrag. Tauschen Sie IID oder CLSID nach der Veröffentlichung leichtfertig aus, brechen bestehende VBA-Verweise und -Registrierungen.

10.4 Veröffentlichte Schnittstellen nicht brechen

Bei COM kann selbst „nachträglich nur eine Methode hinzugefügt“ nicht folgenlos bleiben.

  • ICalculator beibehalten
  • Bei größeren Änderungen eine neue ICalculator2 einführen
  • Die Klasse darf ruhig beide implementieren

10.5 Bei Typen zurückhaltend bleiben

An der Grenzfläche zu VBA ist es sicherer, nicht zu ausgefallen zu werden.

Gut geeignet sind zunächst vor allem diese.

  • int
  • double
  • bool
  • string
  • DateTime
  • decimal
  • enum

10.6 Nicht aktualisieren, während Office geöffnet ist

Excel oder Access können die DLL weiterhin gesperrt halten, was bei Build oder Neuregistrierung zu Problemen führen kann.

  • Office schließen
  • Bei Bedarf die Registrierung aufheben
  • Neu bauen
  • Erneut registrieren

Das Aufheben der Registrierung erfolgt in der umgekehrten Reihenfolge zur Registrierung, mit dem Befehl derselben Bitness, die auch bei der Registrierung verwendet wurde. Auch hier sind Administratorrechte erforderlich, genau wie bei der Registrierung.

# Für 64-Bit-Office / 64-Bit-COM
$out = Resolve-Path .\bin\Release\net8.0-windows

dscom tlbunregister "$out\VbaTypedComSample.tlb"
C:\Windows\System32\regsvr32.exe /u "$out\VbaTypedComSample.comhost.dll"
# Für 32-Bit-Office (auf 64-Bit-Windows)
$out = Resolve-Path .\bin\Release\net8.0-windows

.\tools\dscom32.exe tlbunregister "$out\VbaTypedComSample.tlb"
C:\Windows\SysWOW64\regsvr32.exe /u "$out\VbaTypedComSample.comhost.dll"

/u bei regsvr32 ist die Option zum Aufheben der Registrierung. Verwenden Sie ein anderes regsvr32 als bei der Registrierung, lässt sie sich nicht aufheben (eine mit 64-Bit registrierte Komponente können Sie nicht mit dem regsvr32 aus SysWOW64 entfernen). Heben Sie die Registrierung nicht auf, bevor Sie den gesamten Ordner verschieben oder löschen, bleibt in der Registrierung ein Eintrag mit einem nicht mehr existierenden Pfad zurück.

11. Zusammenfassung

Das Thema „eine .NET 8-DLL typisiert aus VBA verwenden“ ist kein besonders beängstigendes Verfahren, wenn Sie es auf COM-Freigabe + TLB-Erzeugung mit dscom eingrenzen. Auf der .NET 8-Seite setzen Sie EnableComHosting=true und bereiten explizite Schnittstellen vor (Klasse ClassInterfaceType.None, die VBA-seitige Schnittstelle InterfaceIsDual), erzeugen mit dscom tlbexport die TLB, registrieren *.comhost.dll mit regsvr32 und *.tlb mit dscom tlbregister. Danach müssen Sie in VBA nur noch den Verweis setzen und früh binden.

Im Zweifelsfall hilft es, COM-Host und TLB getrennt zu betrachten.

  • Der Starteinstiegspunkt ist *.comhost.dll
  • Die Typinformationen sind in *.tlb
  • Die eigentliche Implementierung ist *.dll

12. Referenzen

Aktuelle Artikel mit denselben Schlagwörtern führen zu verwandten Themen weiter.

Diese Seiten ordnen den Artikel in einen größeren Leistungs- und Entscheidungskontext ein.

Dieser Artikel ist direkt mit den folgenden Leistungen verbunden.

Windows-App-Entwicklung

Das Design der Verbindungsebene über VBA, COM, Office, .NET 8 bis hin zur Erzeugung von Typbibliotheken ist eng mit der Windows-Anwendungsentwicklung verknüpft, weshalb dieses Thema gut zur Windows-Anwendungsentwicklung passt.

Technische Beratung und Design-Review

Wenn Sie das Grenzflächendesign zwischen bestehenden VBA-Beständen und .NET 8 – einschließlich Bitness, Registrierung, TLB-Erzeugung und Verteilungsstrategie – strukturiert angehen möchten, lässt sich das gut als technische Beratung und Design-Review durchführen.

Häufige Fragen

Fragen, die in Beratungen zu diesem Artikelthema häufig gestellt werden.

Was benötige ich, um eine .NET 8-DLL aus VBA typisiert (mit früher Bindung) zu verwenden?
Sie bauen die .NET 8-Klassenbibliothek mit EnableComHosting=true, wodurch *.comhost.dll entsteht, und erzeugen mit dscom tlbexport eine *.tlb. Anschließend registrieren Sie *.comhost.dll mit regsvr32 und *.tlb mit dscom tlbregister und fügen diese TLB in VBA über die Verweise hinzu – danach können Sie sie typisiert in der Form Dim x As `Bibliotheksname.IYourInterface` verwenden. Die Rollenverteilung ist: *.comhost.dll ist der COM-Starteinstiegspunkt, *.tlb sind die Typinformationen, die VBA sieht, und *.dll ist die eigentliche Implementierung.
Was ist die Ursache für die Meldung „ActiveX-Komponente kann kein Objekt erstellen“?
Die typische Ursache ist eine Bitness-Diskrepanz zwischen Office/VBA und dem COM-Server. Bei 64-Bit-Office bauen Sie für x64/win-x64 und registrieren mit dem regsvr32 aus System32; bei 32-Bit-Office (auf 64-Bit-Windows) bauen Sie für x86/win-x86, registrieren mit dem regsvr32 aus SysWOW64 und erzeugen die TLB ebenfalls mit dscom32.exe. Bleibt ein COM-Host unter .NET 5+ auf AnyCPU, neigt die *.comhost.dll dazu, in Richtung 64-Bit zu wandern, was mit 32-Bit-Office nicht zusammenpasst – deshalb ist es sicherer, x86/x64 passend zu Office explizit anzugeben.
Darf ich ClassInterfaceType.AutoDual nicht verwenden?
Es wirkt zunächst bequem, sollte aber vermieden werden, weil es leicht bricht, sobald Sie nach der Veröffentlichung die Reihenfolge oder Zusammensetzung der Member ändern. Wenn Sie stabil typisiert aus VBA arbeiten möchten, ist es bewährte Praxis, explizite Schnittstellen zu definieren, die Klasse auf ClassInterfaceType.None zu setzen und die von VBA verwendete Schnittstelle auf InterfaceIsDual zu setzen. Das Vergeben von DispId verringert Unfälle, wenn sich später die Methodenreihenfolge ändert. Da in COM die GUID selbst den Vertrag darstellt, brechen zudem bestehende VBA-Verweise und -Registrierungen, wenn Sie IID oder CLSID nach der Veröffentlichung leichtfertig neu erzeugen.
Reicht es, beim Verteilen nur die DLL allein weiterzugeben?
Nein, mit der DLL allein funktioniert es nicht. Sie müssen die eigentliche Implementierung *.dll, *.comhost.dll, *.deps.json, *.runtimeconfig.json, *.tlb sowie bei Bedarf sämtliche abhängigen DLLs gemeinsam bereitstellen. Zusätzlich benötigt der Client-PC die passende .NET 8-Laufzeit, da der COM-Host nicht als self-contained, sondern grundsätzlich framework-dependent betrieben wird. Beachten Sie außerdem, dass eine spätere Verschiebung des Ablageorts auch eine erneute Registrierung erfordert.

Autorenprofil

Profilseite des Artikelautors.

Go Komura

Geschäftsführer von KomuraSoft LLC

Spezialisiert auf Windows-Softwareentwicklung, technische Beratung und Fehleranalyse, insbesondere bei bestehenden Systemen und schwer reproduzierbaren Störungen.

Zurück zum Blog