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=truebauen - Eine explizite Schnittstelle und eine Klasse erstellen, die COM zeigt
- Die Klasse auf
ClassInterfaceType.Nonesetzen und nicht aufAutoDualausweichen - Die aus VBA verwendete Schnittstelle auf
InterfaceIsDualsetzen - Aus der nach dem Build entstandenen
*.dllmitdscom tlbexporteine*.tlberzeugen - Die
*.comhost.dllmitregsvr32registrieren - Die
*.tlbmitdscom tlbregisterregistrieren - 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.
flowchart LR
VBA["VBA / Excel / Access"] -->|"Typinformationen aus der referenzierten TLB"| TLB["VbaTypedComSample.tlb"]
VBA -->|"COM-Aufruf"| COMHOST["VbaTypedComSample.comhost.dll"]
COMHOST --> DOTNET["VbaTypedComSample.dll (.NET 8)"]
DOTNET --> RUNTIME[".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
Guidgetrennt 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
DispIdverringert Unfälle, wenn Sie nach der Veröffentlichung die Methodenreihenfolge ändern - Da COM die Klasse per
Newerzeugt, 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.
- Bezugsquelle: https://github.com/dspace-group/dscom/releases
dscom.exe… erzeugt aus einer AnyCPU- oder 64-Bit-Assembly eine 64-Bit-TLBdscom32.exe… erzeugt aus einer AnyCPU- oder 32-Bit-Assembly eine 32-Bit-TLB
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.
regsvr32registriert*.comhost.dllals COM-Servertlbregisterregistriert*.tlbals Typbibliothek
8. In VBA einen Verweis hinzufügen und typisiert verwenden
- Excel oder Access öffnen
- Mit
Alt+F11den VBA-Editor (VBE) öffnen. Über das Menüband öffnen Sie ihn unterEntwicklertools>Visual Basic. Wird die RegisterkarteEntwicklertoolsnicht angezeigt, aktivieren Sie sie unterDatei>Optionen>Menüband anpassenmit dem Häkchen beiEntwicklertools - Im VBE-Menü
Extras>Verweise - Die Liste
Verfügbare Verweiseist alphabetisch sortiert. War die Registrierung erfolgreich, erscheint dort der Bibliotheksname (standardmäßig identisch mit dem AssemblynamenVbaTypedComSample) – setzen Sie das Häkchen links davon und klicken Sie aufOK - Erscheint er nicht in der Liste, wählen Sie über die Schaltfläche
Durchsuchen...direktVbaTypedComSample.tlbaus
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/x86explizit 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-runtimesausführen und prüfen, ob eine Zeile mitMicrosoft.NETCore.App 8.xerscheint
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.
ICalculatorbeibehalten- Bei größeren Änderungen eine neue
ICalculator2einfü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.
intdoubleboolstringDateTimedecimalenum
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
- Vollständiger Beispielcode zu diesem Artikel (COM-freigegebene Bibliothek, Skripte, VBA, Tests) - komurasoft-blog-samples (GitHub)
- Expose .NET components to COM - Microsoft Learn
- .NET-Typen für die COM-Interoperabilität qualifizieren - Microsoft Learn
- ComInterfaceType-Enumeration - Microsoft Learn
- ClassInterfaceType-Enumeration - Microsoft Learn
- COM Callable Wrapper - Microsoft Learn
- DispIdAttribute-Klasse - Microsoft Learn
- dscom - NuGet Gallery
- dspace-group/dscom - GitHub (dscom selbst. Enthält die Liste der Subbefehle und Erläuterungen zur 32-Bit-Unterstützung)
- Releaseseite von dscom (Bezugsquelle für
dscom32.exe) - Zuordnen von HRESULTs und Ausnahmen - Microsoft Learn
- How to use the Regsvr32 tool and troubleshoot Regsvr32 error messages - Microsoft Support
- .NET 8 downloads
Verwandte Artikel
Aktuelle Artikel mit denselben Schlagwörtern führen zu verwandten Themen weiter.
Warum EXCEL.EXE-Prozesse nach C#-Excel-COM-Automatisierung bestehen bleiben — Muster zur Referenzfreigabe und die Ersatzentscheidung
Ein praxisnaher Blick darauf, warum EXCEL.EXE-Prozesse nach der Automatisierung von Excel aus C# über Microsoft.Office.Interop.Excel best...
Excel-VBA-Makros zu Power Automate migrieren — Was Sie durch Office-Skripte ersetzen können, und was als VBA bleiben sollte
Ein Leitfaden dazu, ob Excel-VBA-Makros zu Power Automate migrieren können: Was Office-Skripte ersetzen können, was nur VBA weiterhin lei...
Abwärtskompatibilität von DLL- und COM-Schnittstellen — Eine Entscheidungstabelle dafür, welche Änderungen Aufrufer brechen
Welche Änderungen an einer DLL oder COM-Komponente brechen tatsächlich deren Aufrufer? Wir legen die drei Ebenen der Kompatibilität dar —...
Laufen Business-Anwendungen unter Windows on Arm? ── Die Realität von x64-Emulation (Prism) und nativen DLLs/COM
Eine Antwort für Entwicklerinnen, Entwickler und IT-Verantwortliche auf die Frage „Läuft unsere Business-Anwendung unter Windows on Arm?“...
Windows-Prozesskommunikation richtig wählen ── Eine Entscheidungstabelle für Named Pipes / TCP / gRPC / Shared Memory / COM
Wie wählt man den richtigen Weg, damit Windows-Anwendungen miteinander sprechen? Dieser Artikel ordnet Named Pipes, lokales TCP, gRPC, Sh...
Verwandte Themen
Diese Seiten ordnen den Artikel in einen größeren Leistungs- und Entscheidungskontext ein.
Technische Windows-Themen
Portal zu Windows-Entwicklung, Fehleranalyse und der Nutzung bestehender Assets.
ActiveX-Migration
Entscheidungen zum Beibehalten, Kapseln oder Ersetzen von COM / ActiveX / OCX.
Leistungen zu diesem Thema
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.