Was ist Reg-Free COM - COM ohne Registrierung nutzen
· Go Komura · COM, Reg-Free COM, Registration-Free COM, Windows-Entwicklung, Legacy-Technologie
Bei COM- / ActiveX- / OCX-Projekten taucht bei jeder Verteilung und Aktualisierung dasselbe Problem wieder auf.
regsvr32wird benötigt- Administratorrechte werden meist erforderlich
- Es kollidiert mit einer anderen Version, die eine andere Anwendung installiert hat
- Eine Deinstallation reißt andere Produkte mit
- Es funktioniert auf dem Entwicklungsrechner, aber nicht in einer sauberen Umgebung
Diesen Aufwand kann Reg-Free COM erheblich reduzieren. Allerdings ist es trotz seines Namens keine „Magie, die alle Umstände von COM zum Verschwinden bringt“. Was verschwindet, sind vor allem die Umstände, die durch die globale Registrierung mitgeschleppt werden. Bitness, abhängige DLLs, Typbibliotheken und die Schwierigkeiten des Threading-Modells bleiben bestehen.
Dieser Artikel ordnet Reg-Free COM vor allem im Kontext ein, COM-DLLs / OCX-Steuerelemente in Windows-Desktopanwendungen app-lokal einzuschließen und zu nutzen.
Zielgruppe und Voraussetzungen
Dieser Artikel richtet sich an Entwickler, die eine Windows-Desktopanwendung mit vorhandenen COM-DLLs / OCX-Steuerelementen verteilen und von regsvr32 sowie Administratorrechten wegkommen möchten. Vorausgesetzt wird, dass Sie die Grundlagen von COM (CLSID, ProgID, CoCreateInstance, In-Proc-Server) schon einmal angefasst haben. Ist das noch unklar, lohnt es sich, zuerst „Was sind COM / ActiveX / OCX? – Unterschiede und Zusammenhänge im Überblick“ zu lesen.
Der praktische Teil verwendet mt.exe und sxstrace aus dem Windows SDK, es wird also eine Umgebung mit Visual Studio oder dem Windows SDK vorausgesetzt.
1. Das Fazit zuerst (in einem Satz)
Zunächst eine grobe, aber nützliche Formulierung.
- Reg-Free COM ist eine Methode, COM-Registrierungsinformationen in einem Manifest statt in der Registry zu führen
- Zur Laufzeit wird bei der Auflösung von
CoCreateInstanceoderCLSIDFromProgIDzuerst der Aktivierungskontext betrachtet - Dadurch lassen sich COM-DLLs / OCX-Steuerelemente pro Anwendung privat halten
- Die wichtigsten Vorteile sind eine leichte XCOPY-Verteilung, leichter vermeidbare Versionskonflikte und weniger anfällige Deinstallationen
- Allerdings verschwindet das 32-Bit- / 64-Bit-Problem nicht. Das lässt sich durch die Art der Manifesterstellung nicht umgehen
- Außerdem müssen abhängige DLLs, Typbibliotheken, Entwurfszeit-Verweise und Abhängigkeiten von nicht standardmäßigen Registrierungsinformationen separat bedacht werden
- In der Praxis passt es sehr gut, wenn Sie anwendungseigene COM-Komponenten mitgeben möchten
Kurz gesagt: Reg-Free COM ist ein Mechanismus, der die COM-Aktivierung wieder auf die Anwendungsebene zurückholt.
2. Was dieser Artikel unter Reg-Free COM versteht
Reg-Free COM ist die Kurzform von Registration-Free COM. Im Japanischen wird es manchmal auch als „registrierungsfreies COM“ umschrieben.
„Registrierungsfrei“ bedeutet hier: um COM zu nutzen, nicht vollständig auf die globale Registry-Registrierung unter HKCR / CLSID / InprocServer32 angewiesen zu sein.
Es bedeutet weder, dass COM selbst verschwindet, noch dass GUIDs überflüssig werden.
Dieser Artikel behandelt vor allem Dinge wie diese.
- Native COM-DLLs
- ATL-basierte COM-Server
- ActiveX / OCX
- COM-Interop auf Basis von .NET Framework
- Freigabe über den COM-Host von .NET 5+ / .NET 8
Umgekehrt möchten wir zwei Punkte besonders betonen.
- Reg-Free COM ist ein Thema der „Aktivierung“
- Die Verteilung von Typinformationen und Entwurfszeit-Verweise können als eigenes Thema bestehen bleiben
Vermischt man das, wird die Sache ziemlich unscharf.
3. Zunächst auf einen Blick
Bevor wir zur Grafik kommen, definieren wir vorab nur die vier Begriffe, die in diesem Artikel immer wieder auftauchen.
| Begriff | Bedeutung |
|---|---|
| Aktivierungskontext (activation context) | Eine Laufzeit-Datenstruktur, die festhält, „welche Version welcher Assembly dieser Thread gerade verwendet“. CoCreateInstance sieht hier zuerst nach, noch vor der Registry |
| side-by-side assembly | Der Windows-Mechanismus, um Komponenten mit demselben Namen in unterschiedlichen Versionen auf derselben Maschine koexistieren zu lassen. Identifiziert über das Manifest, mit assemblyIdentity als Namensschild |
| Anwendungsmanifest | Das XML auf Seiten der EXE, das festlegt, „von welcher side-by-side assembly diese Anwendung abhängt“ |
| Komponentenmanifest (assembly manifest) | Das XML auf Seiten der Komponente, das festlegt, „welche Dateien diese Assembly enthält und welche COM-Klassen sie freigibt“. Hier landen die Informationen, die eigentlich in der Registry lagen |
Der Aktivierungskontext wird pro Thread gehalten. COM übergibt den Aktivierungskontext des erstellenden Threads an den Hostthread, bevor LoadLibrary oder DllGetClassObject aufgerufen wird, sodass auf Aufruferseite keine besonderen Vorkehrungen nötig sind.
Danach ist es schneller, sich das Gesamtbild auf einen Blick anzusehen.
flowchart LR
APP["MyApp.exe"] --> AM["Application Manifest"]
AM --> DEP["dependentAssembly"]
DEP --> CM["Component / Assembly Manifest"]
CM --> META["file / comClass / typelib"]
META --> DLL["VendorControl.dll / .ocx"]
APP --> ACTX["Activation Context"]
ACTX --> COM["CLSIDFromProgID / CoCreateInstance"]
COM --> DLL
Bei gewöhnlichem COM wird beim Aufruf von CoCreateInstance die Registry durchlaufen, um zu entscheiden, welche DLL geladen wird.
Bei Reg-Free COM wird davor der gerade aktive Aktivierungskontext betrachtet und anhand der dort hinterlegten Manifestinformationen aufgelöst.
Dadurch können Anwendung A und Anwendung B auf derselben Maschine leichter unterschiedliche Versionen derselben COM-Komponentenfamilie gleichzeitig betreiben. Die Kultur des COM-Teilens wird dadurch ein Stück weit in Richtung app-lokal zurückgeholt.
4. Warum die gewöhnliche COM-Verteilung schwer wird
Die gewöhnliche COM-Verteilung ist nicht schwer, weil COM selbst schlecht wäre, sondern weil sie auf globaler Registrierung beruht.
Um eine COM-Klasse zu nutzen, werden ungefähr diese Informationen benötigt.
| Information | Rolle |
|---|---|
| CLSID | Die GUID, die eine Klasse eindeutig identifiziert |
| ProgID | Ein für Menschen handhabbarer Name |
| InprocServer32 | Welche DLL geladen wird |
| ThreadingModel | Die Voraussetzung wie Apartment / Both |
| TypeLib | Typinformationen |
Landen diese in der Registry, ist das maschinenweit praktisch, weil es sich leicht von mehreren Anwendungen teilen lässt.
In der Praxis schlägt dieses Teilen jedoch oft ins Gegenteil um.
- Das Setup eines Produkts überschreibt die COM-Registrierung eines anderen Produkts
- Ein Deinstallationsprogramm meint, nur „das Eigene“ zu löschen, beschädigt aber geteiltes COM
- Eine auf dem Entwicklungsrechner zufällig vorhandene Registrierung fehlt auf der Produktionsmaschine
- 32-Bit- und 64-Bit-Registrierung passen nicht zusammen, und nur die Symptome verschieben sich auf unheimliche Weise
Kurz gesagt: Nicht COM selbst, sondern das Verteilungsmodell bereitet häufiger Probleme. Reg-Free COM ist ein Mechanismus, um genau diese Schwierigkeit des Verteilungsmodells zu verringern.
5. Wie Reg-Free COM funktioniert
5.1. Das Anwendungsmanifest beschreibt die Abhängigkeit
Zunächst schreibt die Anwendungsseite in ihr Anwendungsmanifest, von welcher side-by-side assembly sie abhängt.
Dieses Manifest kann auf zwei Arten gehandhabt werden:
- als
MyApp.exe.manifestneben der EXE platziert - als Ressource in die EXE eingebettet
Praktisch gilt oft: eine externe Datei, wenn Verteilung und Austausch übersichtlich bleiben sollen, und Einbettung, wenn Robustheit und einfache Verteilung Vorrang haben.
Existieren sowohl eine externe als auch eine eingebettete Version, hat das Manifest im Dateisystem Vorrang.
5.2. Das Komponentenmanifest beschreibt die COM-Informationen
Als Nächstes führt die COM-Seite die eigentlich in der Registry enthaltenen Informationen im Komponentenmanifest.
Hier stehen zum Beispiel Informationen wie diese.
comClassclsidprogidthreadingModeltypelib- bei Bedarf proxy / stub oder Fensterklassen und Ähnliches
Kurz gesagt: Statt der Registry wird das Erscheinungsbild von COM in XML beschrieben.
Dieses Manifest lässt sich auf zwei Arten aufbauen:
- als separate Datei neben der DLL
- als Ressource in die DLL eingebettet
In der Praxis passiert weniger, wenn man es als private assembly in die DLL einbettet. Der Betrieb als separate Datei ist zwar leicht verständlich, birgt aber leicht Stolperfallen bei der Übereinstimmung von Dateinamen und assemblyIdentity, beim Ablageort und bei vergessenen Kopien.
5.3. Zur Laufzeit wird zuerst der Aktivierungskontext betrachtet
Hier liegt der Kern von Reg-Free COM.
Ruft die Anwendung CLSIDFromProgID oder CoCreateInstance auf, betrachtet die COM-Laufzeit den aktiven Aktivierungskontext.
Sind dort die nötigen Informationen von ProgID → CLSID und CLSID → DLL vorhanden, lässt sich ohne Registry auflösen.
Fehlen dem Manifest umgekehrt die nötigen Informationen, fällt es auf die übliche registrierungsbasierte Auflösung zurück. Wegen dieses Verhaltens entsteht die Falle, dass es auf dem Entwicklungsrechner zufällig funktioniert. Man glaubt, Reg-Free erreicht zu haben, wird in Wirklichkeit aber von der lokalen Registrierung gerettet.
Das ist die heimtückischste Falle bei Reg-Free COM.
6. Was ist der Nutzen davon
Die Vorteile von Reg-Free COM sind in der Praxis ziemlich klar.
6.1. Leichte XCOPY-Verteilung
Da sich die benötigten Dateien gesammelt im Anwendungsordner ablegen lassen, werden Installer und Registrierungsschritte leichter.
Natürlich ist das Schreiben unter Program Files eine eigene Frage der Rechte, aber zumindest lässt sich der Administratoraufwand für die COM-Registrierung meist reduzieren.
6.2. Leichter vermeidbare Versionskonflikte
Auch wenn mehrere Versionen einer COM-Komponente auf derselben Maschine vorliegen, lässt sich leichter steuern, welche Version welche Anwendung nutzt. Der Vorfall „ein anderes Produkt wurde installiert, und plötzlich hat sich das Verhalten geändert“ lässt sich dadurch deutlich leichter vermeiden.
6.3. Oft ohne größere Änderung am bestehenden Code
Reg-Free COM ändert nicht grundlegend, wie bestehender Code aufgerufen wird, sondern die Art der Auflösung.
Passt es gut, lässt es sich deshalb einführen, ohne den CoCreateInstance-Code kaum anzufassen.
6.4. Löschen und Rollback werden einfacher
Da alles auf Anwendungsebene eingeschlossen ist, werden Aktualisierung und Rollback deutlich unkomplizierter. Im Extremfall wird der Gedanke „den ganzen Ordner austauschen“ durchführbar.
7. Geeignete und weniger geeignete Situationen
7.1. Geeignete Situationen
In diesen Fällen ist Reg-Free COM eine ziemlich starke Option.
| Situation | Eignung |
|---|---|
| Sie möchten eine anwendungseigene COM-DLL / ein OCX mitliefern | Sehr gut |
| Sie möchten mehrere Versionen auf demselben PC koexistieren lassen | Sehr gut |
| Sie möchten Registrierungsunfälle mit Herstellerkomponenten vermeiden | Gut |
| Sie möchten ActiveX / OCX in einer bestehenden Desktopanwendung privat nutzen | Gut |
| Sie möchten die Verteilung schlank halten, ohne bestehende Aufrufe stark zu ändern | Gut |
Typischerweise passt es gut zu betrieblichen Desktopanwendungen, Anlagenanbindungs-Tools sowie bestehenden VB6- / MFC- / WinForms-Beständen.
7.2. Ungeeignete oder mit Vorsicht zu betrachtende Situationen
Andererseits gibt es Fälle, die man mit Vorsicht betrachten sollte.
| Situation | Kommentar |
|---|---|
| Sie möchten COM maschinenweit teilen | Der Nutzen von Reg-Free ist gering |
| Die Bitness passt nicht zusammen | Reg-Free löst das nicht |
| Es besteht eine starke Abhängigkeit von nicht standardmäßigen Registrierungsinformationen oder einem eigenen Setup | Schwer in ein Manifest zu überführen |
| Die Verteilung abhängiger DLLs oder der VC++-Laufzeit ist nicht geklärt | Es scheitert am Ende an anderer Stelle |
| Entwurfszeit-Tools oder die Verweiseinstellungen der IDE setzen die Registry voraus | Ein anderes Betriebskonzept ist nötig |
Besonders der letzte Punkt ist wichtig. Reg-Free COM unterstützt die Aktivierung zur Laufzeit, ändert aber nicht auf einen Schlag, worauf die UI für Entwurfszeit-Verweise aufbaut.
8. Häufige Missverständnisse
8.1. Mit Reg-Free COM verschwindet das Bitness-Problem
Nein. Ein 32-Bit-Prozess kann nur 32-Bit-In-Proc-COM-DLLs laden, ein 64-Bit-Prozess nur 64-Bit-DLLs. Daran ändert Reg-Free nichts.
8.2. Mit Reg-Free COM wird die Registry überhaupt nicht mehr angesehen
Auch das stimmt nicht. Fehlen dem Manifest die nötigen Informationen, fällt es auf die übliche registrierungsbasierte Auflösung zurück. Deshalb bedeutet Erfolg auf dem Entwicklungsrechner nicht zwangsläufig, dass die Reg-Free-Konfiguration korrekt ist.
8.3. Mit Reg-Free COM erledigt sich auch die Frage der Typbibliothek automatisch
Das stimmt nur zur Hälfte.
Das Manifest kann zwar auch typelib-Informationen enthalten, aber der Umgang mit Typinformationen — VBA-Verweiseinstellungen, #import in C++, die Erzeugung von Entwurfszeit-Verweisen auf .NET-Seite — erfordert häufig ein eigenes Design.
Reg-Free COM sorgt zunächst dafür, dass etwas überhaupt startet. Wie typisiert entwickelt wird, ist das nächste Thema.
8.4. Mit Reg-Free COM lässt sich jedes ActiveX / OCX unverändert übernehmen
Auch das ist riskant. Beruht die Komponente auf standardmäßigen COM-Registrierungsinformationen, lässt es sich gut vorantreiben, aber bei starker Abhängigkeit von eigenen Registry-Einstellungen, zusätzlichem Setup, Lizenzverarbeitung oder weiteren Modulgruppen wird die Umstellung auf Reg-Free plötzlich zäh.
8.5. Reg-Free COM ist bei .NET Framework und .NET 8 im Grunde gleich
Es gibt Ähnlichkeiten, aber die Toolchain unterscheidet sich deutlich.
Der Kontext von .NET Framework + RegAsm und der Kontext von .NET 5+ / .NET 8 + comhost haben, obwohl es in beiden Fällen um COM geht, eine unterschiedliche Grundlage.
9. Unterschiede zwischen nativ / .NET Framework / .NET 5+ / .NET 8
Das wird leicht vermischt, deshalb betrachten wir es hier getrennt.
| Familie | Grobe Einordnung |
|---|---|
| Native COM-DLL / OCX | Grundsätzlich mit Anwendungsmanifest + Komponentenmanifest gedacht |
| .NET-Framework-basiertes COM-Interop | Zusätzlich zum Anwendungsmanifest im Win32-Stil wird auch ein Manifest auf Seiten der Managed-Komponente benötigt |
| COM-Freigabe mit .NET 5+ / .NET 8 | EnableComHosting erzeugt den COM-Host, EnableRegFreeCom erzeugt das Reg-Free-Manifest |
9.1. COM auf Basis von .NET Framework
Bei COM auf Basis von .NET Framework gibt es zwei Ebenen: das Application Manifest im Win32-Stil auf Seiten der COM-Anwendung und das Component Manifest auf Seiten der Managed-Komponente.
Es kommt also im Vergleich zu nativem COM ein weiteres Manifest hinzu. Die Einschränkungen zu Name und Ressourcen-ID aus 10.4 gelten ebenso für dieses Component Manifest.
9.2. COM-Freigabe mit .NET 5+ / .NET 8
Bei .NET 5+ / .NET 8 wird *.comhost.dll zum Einstiegspunkt für die COM-Freigabe.
Setzt man zusätzlich EnableRegFreeCom=true, wird das side-by-side manifest für Reg-Free COM ausgegeben.
Dass der Umgang mit Typinformationen ein eigenes Thema ist, gilt wie in 8.3 beschrieben, ändert sich aber bei .NET Core / .NET 5+ noch weiter. Da hier nicht mehr die TLB von selbst aus der Assembly entsteht wie zu .NET-Framework-Zeiten, muss bei Bedarf typisierter Nutzung die Erzeugung, Einbettung und Registrierung der TLB gesondert aufgebaut werden. Die konkreten Schritte sind in „.NET 8-DLL typisiert aus VBA verwenden - COM-Freigabe und dscom-TLB“ zusammengefasst.
10. Bild einer minimalen Konfiguration
Hier zeigen wir das minimale Bild dafür, dass MyApp.exe Vendor.CameraControl.dll per Reg-Free COM verwendet.
10.1. Bild der Dateistruktur
MyApp.exe
MyApp.exe.manifest
Vendor.CameraControl.Asm.manifest
Vendor.CameraControl.dll
Vendor.Helper.dll
Im obigen Beispiel wird davon ausgegangen, dass das Komponentenmanifest als separate Datei abgelegt ist. Es lässt sich auch in die DLL einbetten, dann gelten aber feste Einschränkungen für den Namen der Assembly und die Ressourcen-ID. Das gesamte Vorgehen wird in 10.4 behandelt.
10.2. Bild des Anwendungsmanifests
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity
type="win32"
name="KomuraSoft.MyApp"
version="1.0.0.0"
processorArchitecture="amd64" />
<dependency>
<dependentAssembly>
<assemblyIdentity
type="win32"
name="Vendor.CameraControl.Asm"
version="1.0.0.0"
processorArchitecture="amd64" />
</dependentAssembly>
</dependency>
</assembly>
10.3. Bild des Komponentenmanifests
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity
type="win32"
name="Vendor.CameraControl.Asm"
version="1.0.0.0"
processorArchitecture="amd64" />
<file name="Vendor.CameraControl.dll">
<comClass
clsid="{01234567-89AB-CDEF-0123-456789ABCDEF}"
progid="Vendor.CameraControl.1"
threadingModel="Apartment"
tlbid="{89ABCDEF-0123-4567-89AB-CDEF01234567}" />
<typelib
tlbid="{89ABCDEF-0123-4567-89AB-CDEF01234567}"
version="1.0"
helpdir="" />
</file>
</assembly>
Bei diesem Beispiel kommt es weniger auf die Details des XML an, sondern wirklich darauf, dass dependentAssembly auf Anwendungsseite und assemblyIdentity auf Komponentenseite übereinstimmen.
Weicht das voneinander ab, entsteht ein Startfehler, dessen Ursache sich allein am Erscheinungsbild der Fehlermeldung nicht erkennen lässt.
Die GUIDs und Namen oben sind erläuternde Beispiele. In der Praxis müssen Sie sie korrekt an die von der Komponente tatsächlich freigegebenen CLSID / TLBID / ProgID / das Threading-Modell anpassen.
10.4. Wohin das Manifest gehört und wie es eingebettet wird
Hier stolpert man am häufigsten. Je nachdem, ob Sie es als separate Datei ablegen oder in die Binärdatei einbetten, ändert sich, welcher Name erlaubt ist.
Side-by-side durchsucht private assemblies relativ zum Anwendungsordner in dieser Reihenfolge.
- WinSxS-Ordner
<appdir>\<assemblyname>.DLL<appdir>\<assemblyname>.manifest<appdir>\<assemblyname>\<assemblyname>.DLL<appdir>\<assemblyname>\<assemblyname>.manifest
Wird zuerst eine DLL mit demselben Namen wie die assembly gefunden, stoppt die Suche dort. Daraus ergeben sich nur diese zwei möglichen Varianten.
| Ablageart | Assembly-Name | Datei | Ressourcen-ID beim Einbetten |
|---|---|---|---|
| Separate Datei | Anderer Name als die DLL, z. B. Vendor.CameraControl.Asm |
Vendor.CameraControl.Asm.manifest neben der DLL ablegen |
Nicht eingebettet |
| Einbettung in die DLL | Kann derselbe Name wie die DLL sein, z. B. Vendor.CameraControl |
Nur Vendor.CameraControl.dll |
1 |
Verwenden Sie also wie in den Beispielen 10.2 und 10.3 den Namen Vendor.CameraControl.Asm, ist das die Konvention für separate Dateien. Wechseln Sie zur Einbettung, ändern Sie den name von assemblyIdentity zu Vendor.CameraControl und gleichen Sie den Namen auf Seite von dependentAssembly entsprechend an.
Es gibt noch eine weitere leicht zu verwechselnde Einschränkung. Das Komponentenmanifest lässt sich nicht in die Ressourcen der EXE einbetten. In die EXE gehört das Anwendungsmanifest.
Für das Einbetten wird mt.exe (das Manifest-Tool) aus dem Windows SDK verwendet. Führen Sie es aus der Entwicklereingabeaufforderung von Visual Studio aus.
rem 1. Vor dem Einbetten zunächst die Syntax prüfen
mt.exe -manifest MyApp.exe.manifest -validate_manifest
mt.exe -manifest Vendor.CameraControl.manifest -validate_manifest
rem 2. Das Anwendungsmanifest in die EXE einbetten
mt.exe -manifest MyApp.exe.manifest -outputresource:MyApp.exe;#1
rem 3. Das Komponentenmanifest in die DLL einbetten (Ressourcen-ID ist 1)
mt.exe -manifest Vendor.CameraControl.manifest -outputresource:Vendor.CameraControl.dll;#1
rem 4. Prüfen, ob die Einbettung geklappt hat, indem sie wieder herausgelöst wird
mt.exe -inputresource:Vendor.CameraControl.dll;#1 -out:extracted.manifest
Vergleicht man das mit dem vierten Befehl herausgelöste extracted.manifest mit dem ursprünglichen XML, lässt sich ausschließen, dass „es sollte eingebettet sein, war es aber nicht“.
Bei mt.exe gibt es zwei Dinge zu beachten.
- Die vom Manifest referenzierten Dateien müssen im selben Verzeichnis wie das Manifest liegen. Steht dort
<file name="Vendor.CameraControl.dll">, legen Sie diese DLL vor der Ausführung neben das Manifest. Sind Build-Ausgabe und Manifest-Ablageort getrennt, bleibt der Vorgang hier stecken - Lassen Sie bei
-outputresourcedie Ressourcen-ID weg, wirdCREATEPROCESS_MANIFEST_RESOURCE(= 1) verwendet. Damit ein unbeabsichtigtes 1 keine Probleme macht, ist es lesbarer,;#1explizit anzugeben
Wollen Sie nur eine bereits eingebettete Version austauschen, genügt -updateresource:<Datei>;#1. Das entspricht der Übergabe desselben Arguments an -inputresource und -outputresource.
10.5. Der Prüfablauf einschließlich einer sauberen Umgebung
Bei Reg-Free COM bedeutet „es hat auf dem Entwicklungsrechner funktioniert“ so gut wie nichts. Denn es besteht immer die Möglichkeit, dass es nur von einer lokalen Registry-Registrierung gerettet wurde. Prüfen Sie in dieser Reihenfolge.
- Bauen Sie es, und fassen Sie das gesamte Verteilungspaket in einem Ordner zusammen. EXE, Manifeste, COM-DLL, abhängige DLLs, VC++-Laufzeit, bis hin zu proxy- / stub-DLLs
- Bereiten Sie eine Testumgebung vor. Ideal ist eine Umgebung, in der die betreffende COM-Komponente noch nie registriert wurde. Mit Windows Sandbox lässt sich jedes Mal von einem sauberen Zustand aus testen
- Bestätigen Sie in dieser Umgebung zuerst, dass die betreffende COM-Komponente unregistriert ist. Ergibt der folgende Befehl einen Fehler, dass der Schlüssel nicht gefunden wurde, ist sie unregistriert
- Kopieren Sie den Ordner, und starten Sie direkt. Führen Sie weder den Installer noch
regsvr32aus - Bestätigen Sie, dass auch die Erzeugung des COM-Objekts durchläuft. Der bloße Start allein prüft keine verzögert erzeugten Komponenten. Bringen Sie tatsächlich den Bildschirm oder die Funktion zum Laufen, bei der
CoCreateInstanceausgeführt wird - Schlägt es fehl, erfassen Sie Logs nach dem Vorgehen aus 11.2
Der in Schritt 3 verwendete Befehl ist dieser.
reg query "HKCR\CLSID\{01234567-89AB-CDEF-0123-456789ABCDEF}" /reg:64
reg query "HKCR\CLSID\{01234567-89AB-CDEF-0123-456789ABCDEF}" /reg:32
reg query "HKCR\Vendor.CameraControl.1"
Die 32-Bit- und die 64-Bit-Registry-Ansicht sind getrennte Dinge, achten Sie also unbedingt darauf, die zur Bitness der Anwendung passende Seite zu betrachten. Es ist sicherer, sowohl /reg:64 als auch /reg:32 zu prüfen.
Möchten Sie es auf dem Entwicklungsrechner ausprobieren, entfernen Sie die Registrierung zunächst mit regsvr32 /u Vendor.CameraControl.dll, bevor Sie prüfen. Da dies jedoch Umgebungen beeinträchtigt, in denen andere Produkte dieselbe COM-Komponente nutzen, ist es sicherer, eine saubere Umgebung vorzubereiten.
11. Stolperfallen
11.1. Es funktioniert auf dem Entwicklungsrechner, aber nicht beim Verteilungsziel
Der erste Verdacht sollte sein, dass es in Wirklichkeit von einer Registry-Registrierung gerettet wurde. Die Verifikation von Reg-Free COM sollte, wenn möglich, in einer sauberen Umgebung erfolgen.
11.2. Der Start scheitert mit „side-by-side configuration is incorrect“
Diese Art von Fehler entsteht durch Inkonsistenzen im Manifest, fehlende abhängige DLLs, eine fehlende VC++-Laufzeit oder eine falsche Architektur.
Der reine Fehlertext allein ist ziemlich unfreundlich, deshalb ist es Standard, dies über das Ereignisprotokoll und sxstrace zu verfolgen.
Öffnen Sie für das Ereignisprotokoll die Ereignisanzeige > Windows-Protokolle > Anwendung und suchen Sie nach Fehlern, deren Quelle SideBySide ist. Dort steht, bei der Auflösung welcher assembly es fehlgeschlagen ist.
sxstrace erfassen Sie, während Sie den Fehler reproduzieren. Öffnen Sie die Eingabeaufforderung sicherheitshalber als Administrator.
rem 1. Ablaufverfolgung starten. Dieses Fenster geöffnet lassen
sxstrace trace -logfile:sxstrace.etl
rem 2. In einem anderen Fenster die Anwendung starten und den Fehler reproduzieren
rem 3. Ablaufverfolgung stoppen. Im Fenster von Schritt 1 Enter drücken, oder aus einem anderen Fenster Folgendes ausführen
sxstrace stoptrace
rem 4. Die rohe .etl-Datei in ein für Menschen lesbares Format umwandeln
sxstrace parse -logfile:sxstrace.etl -outfile:sxstrace.txt
Möchten Sie die Aufforderung zum Stoppen nicht sehen, fügen Sie Schritt 1 -nostop hinzu. Ist die Ausgabe zu lang, schränken Sie sie mit -filter:MyApp.exe in Schritt 4 auf die betreffende Anwendung ein.
In der umgewandelten sxstrace.txt stehen der Reihe nach, welches Manifest gesucht und wo keine Übereinstimmung gefunden wurde. Auch wenn Sie die Namensgebung aus 10.4 falsch angewendet haben, sehen Sie das hier am „gesuchten Dateinamen“.
11.3. Component Manifest und Application Manifest passen nicht zueinander
nameweicht abversionweicht abprocessorArchitectureweicht ab- Das vermeintlich kopierte Manifest ist veraltet
Diese Punkte wirken optisch wie sehr kleine Unterschiede, wirken sich beim Start aber ziemlich stark aus.
11.4. Abhängige DLLs vergessen mitzugeben
Betrachtet man nur Vendor.CameraControl.dll und ist zufrieden, fehlen dahinter geladene Dateien wie Vendor.Helper.dll, die VC++-Laufzeit oder proxy- / stub-DLLs.
Reg-Free COM verringert das Problem der COM-Registrierung, beseitigt aber nicht das Problem der nativen Abhängigkeitsauflösung.
11.5. Die Behandlung von Typbibliotheken oder Verweiseinstellungen wird aufgeschoben
Selbst wenn die Runtime-Activation allein funktioniert, brauchen Sie eine Möglichkeit, Typinformationen zu verteilen, sobald
- Sie aus VBA früh binden möchten
- Sie in C++
#importverwenden möchten - Sie auf .NET-Seite zur Entwurfszeit Interop erzeugen möchten
Reg-Free COM regelt das nicht automatisch vollständig, deshalb ist es wichtig, runtime und design-time getrennt zu betrachten.
12. Zusammenfassung
Reg-Free COM lässt sich in einem Satz zusammenfassen als ein Mechanismus, der COM-Registrierungsinformationen von der gesamten Maschine auf die Anwendungsebene verlagert.
Dadurch ergeben sich diese Vorteile:
- COM-DLLs / OCX-Steuerelemente lassen sich leicht app-lokal einschließen
- Versionskonflikte lassen sich leichter reduzieren
- Verteilung und Rollback lassen sich vereinfachen
Andererseits bleiben diese Punkte weiterhin wichtig:
- 32-Bit / 64-Bit
- Abhängige DLLs
- TLB / Verweiseinstellungen
- Abhängigkeit von nicht standardmäßiger Registrierung
- Verifikation in einer sauberen Umgebung
Die Grundhaltung bei der Einführung von Reg-Free COM lautet daher:
- Sich klarmachen, dass es um Activation geht
- Die Themen runtime und design-time trennen
- In einer sauberen Umgebung prüfen
- Bitness und abhängige DLLs zuerst angleichen
Mit dieser Reihenfolge im Blick passieren deutlich weniger Unfälle.
13. Verwandte Artikel
- Was sind COM / ActiveX / OCX? – Unterschiede und Zusammenhänge im Überblick
- ActiveX / OCX heute behandeln - Entscheidungstabelle: Behalten, Kapseln, Ersetzen
- .NET 8-DLL typisiert aus VBA verwenden - COM-Freigabe und dscom-TLB
14. Referenzen
- Microsoft Learn - Erstellen von Registration-Free COM-Objekten
- Microsoft Learn - Anwendungsmanifeste
- Microsoft Learn - Assembly Manifests (Einschränkungen bei Ressourcen-ID und Name beim Einbetten)
- Microsoft Learn - Assembly Searching Sequence (Suchreihenfolge für private assemblies)
- Microsoft Learn - Manifest File Schema
- Microsoft Learn - Mt.exe
- Microsoft Learn - COM-Interop ohne Registrierung (.NET Framework)
- Microsoft Learn - Verfügbarmachen von .NET Core-Komponenten in COM
- Microsoft Learn - sxstrace
Verwandte Artikel
Aktuelle Artikel mit denselben Schlagwörtern führen zu verwandten Themen weiter.
Was sind COM / ActiveX / OCX? – Unterschiede und Zusammenhänge im Überblick
Wir ordnen praxisnah ein, was COM, was ActiveX und was OCX ist – mit den Unterschieden und Zusammenhängen, der Verbindung zu OLE, den Ein...
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?“...
Wenn Sie ein System ohne Quellcode und ohne Dokumentation übernehmen — Ein praktisches Playbook, um es am Laufen zu halten
Ein praktisches Playbook für den Beginn von Betrieb und Wartung eines Geschäftssystems ohne Quellcode und ohne Spezifikationen. Behandelt...
Wie lange laufen VB6-Anwendungen noch? — Support-Status der Laufzeitumgebung und ein praxisnaher Weg zur .NET-Migration
Wie lange laufen VB6-Anwendungen noch? Dieser Artikel ordnet die Asymmetrie zwischen der Support-Richtlinie für die VB6-Laufzeitumgebung ...
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
Von der Verteilung von COM-DLLs / OCX-Steuerelementen über die Manifeststruktur bis hin zu Bitness und abhängigen DLLs — dieses Thema hängt direkt mit der Implementierung von Windows-Desktopanwendungen zusammen.
Technische Beratung und Design-Review
Auch für die Entscheidung, ob Reg-Free COM eingesetzt oder der registrierungsbasierte Betrieb beibehalten werden soll, und wie Typbibliotheken und Entwurfszeit-Verweise getrennt werden, eignet sich dies gut.
Häufige Fragen
Fragen, die in Beratungen zu diesem Artikelthema häufig gestellt werden.
- Was ist Reg-Free COM?
- Es ist ein Mechanismus, der COM-Registrierungsinformationen nicht in der Registry, sondern in einem Manifest führt — kurz für Registration-Free COM. Bei der Auflösung von CoCreateInstance oder CLSIDFromProgID wird zur Laufzeit zuerst der Aktivierungskontext betrachtet, und die DLL wird anhand der dort hinterlegten Manifestinformationen aufgelöst. Dadurch lassen sich COM-DLLs / OCX-Steuerelemente pro Anwendung privat halten, was die XCOPY-Verteilung erleichtert, Versionskonflikte leichter vermeidbar macht und Deinstallationen weniger anfällig für Nebenwirkungen macht.
- Löst Reg-Free COM auch das 32-Bit- / 64-Bit-Problem?
- Nein. Ein 32-Bit-Prozess kann nur 32-Bit-In-Proc-COM-DLLs laden, ein 64-Bit-Prozess nur 64-Bit-DLLs — daran ändert Reg-Free COM nichts. Auch die Verteilung abhängiger DLLs und der VC++-Laufzeit, Typbibliotheken, Verweise zur Entwurfszeit sowie Abhängigkeiten von nicht standardmäßigen Registrierungsinformationen müssen separat bedacht werden. Was mit Reg-Free COM überwiegend verschwindet, sind lediglich die Umstände, die durch die globale Registrierung mitgeschleppt werden.
- Warum funktioniert eine Reg-Free-COM-Konfiguration auf dem Entwicklungsrechner, aber nicht beim Kunden?
- Der erste Verdacht sollte sein, dass es in Wirklichkeit von einer Registry-Registrierung gerettet wurde. Fehlen dem Manifest die nötigen Informationen, fällt die COM-Laufzeit auf die übliche registrierungsbasierte Auflösung zurück, sodass es auf dem Entwicklungsrechner dank der lokalen Registrierung zufällig funktionieren kann. Deshalb ist es sicherer, Reg-Free COM in einer sauberen Umgebung zu verifizieren. Startet die Anwendung mit „side-by-side configuration is incorrect“ nicht, liegt das meist an einer Inkonsistenz im Manifest oder an fehlenden abhängigen DLLs; das Standardvorgehen ist, dies über das Ereignisprotokoll und sxstrace zu verfolgen.
- Lässt sich auch eine mit .NET 8 erstellte COM-Komponente als Reg-Free COM einrichten?
- Ja. Bei .NET 5+/.NET 8 erzeugt EnableComHosting die *.comhost.dll als Einstiegspunkt für die COM-Freigabe, und mit zusätzlichem EnableRegFreeCom=true wird ein side-by-side manifest für Reg-Free COM ausgegeben. Reg-Free COM und die TLB-Strategie sind allerdings getrennte Fragen. Bei .NET Core / .NET 5+ entsteht die TLB nicht mehr wie zu .NET-Framework-Zeiten von selbst aus der Assembly, weshalb es sicherer ist, die Erzeugung, Einbettung und Registrierung der TLB gesondert zu planen, wenn typisierte Nutzung wie frühe Bindung aus VBA benötigt wird.
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.