Was ist Reg-Free COM - COM ohne Registrierung nutzen

· · 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.

  • regsvr32 wird 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 CoCreateInstance oder CLSIDFromProgID zuerst 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.

  1. Reg-Free COM ist ein Thema der „Aktivierung“
  2. 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.

MyApp.exeApplication ManifestdependentAssemblyComponent / Assembly Manifestfile / comClass / typelibVendorControl.dll / .ocxActivation ContextCLSIDFromProgID / CoCreateInstance

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.manifest neben 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.

  • comClass
  • clsid
  • progid
  • threadingModel
  • typelib
  • 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.

  1. WinSxS-Ordner
  2. <appdir>\<assemblyname>.DLL
  3. <appdir>\<assemblyname>.manifest
  4. <appdir>\<assemblyname>\<assemblyname>.DLL
  5. <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 -outputresource die Ressourcen-ID weg, wird CREATEPROCESS_MANIFEST_RESOURCE (= 1) verwendet. Damit ein unbeabsichtigtes 1 keine Probleme macht, ist es lesbarer, ;#1 explizit 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.

  1. 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
  2. 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
  3. 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
  4. Kopieren Sie den Ordner, und starten Sie direkt. Führen Sie weder den Installer noch regsvr32 aus
  5. 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 CoCreateInstance ausgeführt wird
  6. 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

  • name weicht ab
  • version weicht ab
  • processorArchitecture weicht 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++ #import verwenden 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:

  1. Sich klarmachen, dass es um Activation geht
  2. Die Themen runtime und design-time trennen
  3. In einer sauberen Umgebung prüfen
  4. Bitness und abhängige DLLs zuerst angleichen

Mit dieser Reihenfolge im Blick passieren deutlich weniger Unfälle.

13. Verwandte Artikel

14. 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

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.

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.

Zurück zum Blog