2013-10-10 12 views
11

TL; DR Müssen alle von regsvr32 produzierten Registrierungseinträge in einem SxS-Manifest "reg-free-COM" vorhanden sein und umgekehrt?Welche Tags sind im Manifest für registrierungsfreie COM erforderlich?


Ich versuche, Registrierung frei COM für eine Drittanbieter-Komponente gehen.

Readingupon das Thema, finde ich, dass es mehr Elemente genannt, die in ein manifest gesetzt werden können:

From the docs, können wir die folgenden Tags zu einem Manifest hinzufügen eine COM-Komponente zu beschreiben:

  • assemblyIdentity - die wirklich beschreibt nur die "abstrakte assembly" so weit wie ich kann sagen,
  • comClass - beschreibt die COM-Klasse (IID In Oberfläche). Es scheint, das wird immer benötigt.
  • typelib - wann?
  • comInterfaceExternalProxyStub - wann?
  • comInterfaceProxyStub - wann?

From the other docs for HKEY_LOCAL_MACHINE\SOFTWARE\Classes wir beobachten können, dass es einige Kategorien für die COM-Registrierungseinträge sind:

regsvr42 Mit dem Zeug die DLL zu extrahieren ich regfree bin versucht, ergibt sich ein Manifest, das nur comClass Einträge enthält, keine typelib oder ProxyStub Einträge. (Und ich kreuze überprüfte die Schlüssel geschrieben, die DLL in Frage pdm.dll, MS Process Debug Manager schreibt nur diese Schlüssel, das heißt, es gibt keine Typbibliothek oder Proxy-Stub-Informationen in der Registrierung ersichtlich.)

Wenn die Registrierung enthält nur die Informationen, die sich auf comClass beziehen Bedeutet dies, dass diese Informationen im SxS-Manifest ausreichen oder zusätzliche Informationen im Manifest benötigt werden?


Als Nebenwirkung bemerkte ich, dass die Registrierung ein VersionIndependentProgId und ein ProgId enthält, die eine Versionsnummer am Ende angefügt hat. Das Manifest hat nur einen ProgId Eintrag und die Dokumentation Zustand:

PROGID: Version abhängige Programmbezeichner mit der Komponente COM verbunden. Das Format einer ProgID ist <vendor>.<component>.<version>.

Aber die docs sagen, auch

Das ComClass Element <progid>...</progid> Elemente wie Kinder haben können, die die Version abhängig ProgIDs Liste.

und they say dass das progid-Attribut die versionsunabhängige sein sollte.

Also, was hier zu setzen? Und spielt es überhaupt eine Rolle, wenn der Client keine bestimmte Version anfordert?

+0

PDM wird keine Typbibliothek haben, es hat keine IDispatch-Schnittstellen und Sie müssen CoCreateInstance() verwenden. Und es quakt wie eine freie Thread-in-Prozess-Komponente, so dass kein Proxy/Stub benötigt wird. Was geht hier eigentlich schief? –

+0

@Hans, danke. Nichts geht als solches schief, aber ich war mir nicht sicher, ob es irgendwelche Fallstricke gab. (COM macht mir immer das Gefühl, als würde ich etwas vermissen.) Wenn Sie mir helfen könnten, meine Geschwafel in zwei oder drei wirklich nützliche Fragen zu entwirren, würde ich das schätzen. Ansonsten bin ich zufrieden damit, dass du denkst, alles ist in Ordnung :-) –

Antwort

11

Das Element assemblyIdentity wird immer benötigt, Teil der Manifest-Installation. Sie müssen immer das comClass-Element angeben, es ersetzt den Registrierungsschlüssel HKLM\Software\Classes\CLSID und wird verwendet, um den CoCreateInstance() - Aufruf des Clients funktionieren zu lassen. Das Dateielement benennt die COM-Server-ausführbare Datei.

Der Rest der Schlüssel ist optional, sie werden benötigt, um das Marshalling zu ermöglichen. Marshalling tritt auf, wenn der Clientaufruf in einem anderen Thread ausgeführt werden muss. Das wird immer passieren, wenn der Server und der Client in verschiedenen Prozessen sind, der Fall für einen Out-of-Process-Server oder wenn der Server auf einem anderen Computer ausgeführt wird. Und es kann vorkommen, wenn das im comClass-Element angegebene ThreadingModel dies erfordert. Mit anderen Worten, wenn das COM-Objekt auf einem Thread erstellt wurde, aber auf einem anderen Thread aufgerufen wird und der Server nicht Thread-sicher ist.

RPC implementiert das Marshalling, aber es hat eine Aufgabe zu tun, dass es Hilfe mit benötigt. Es muss wissen, was die Argumente für die Funktion sind, sowie den Rückgabetyp. Damit sie ihre Werte ordnungsgemäß in ein Datenpaket serialisieren kann, das über ein Netzwerk übertragen oder an den Code in einem anderen Thread übergeben werden kann, der den Aufruf ausführt. Dies ist die Aufgabe des Stellvertreters. Der Stub läuft am empfangenden Ende und deserialisiert die Argumente zum Erstellen des Stapelrahmens und führt den Aufruf aus. Der Rückgabewert der Funktion sowie alle Argumentwerte, die als Referenz übergeben werden, kehren dann zum Aufrufer zurück. Der Code, der den Aufruf anders macht, hat überhaupt keine Kenntnis davon, dass er die Funktion nicht direkt aufgerufen hat.

Es gibt vier grundlegende Fälle:

  • Der COM-Server unterstützt nicht überhaupt auf diese Weise aufgerufen werden und muss immer aus dem gleichen Thread verwendet werden, der es erstellt wurde. Stoppen Sie dort, keine Notwendigkeit, dem Manifest etwas hinzuzufügen.

  • Der COM-Server implementiert die IMarshal interface. Wird automatisch von COM abgefragt, wenn keine andere Möglichkeit gefunden wird, den Anruf zu vermitteln. Dies ist ziemlich selten, außer für einen Fall, in dem der COM-Server den Marshaller mit freiem Thread aggregiert. Mit anderen Worten, ist völlig threadsicher, ohne Hilfe zu benötigen und läuft immer im Prozess. PDM wird wahrscheinlich so funktionieren. Stoppen Sie dort, keine Notwendigkeit, dem Manifest etwas hinzuzufügen.

  • Der COM-Server-Autor hat sein Projekt gestartet, indem er die Schnittstellenbeschreibung des Servers in die Sprache IDL geschrieben hat. Das wurde dann von MIDL zusammengestellt. Eine Option, die verfügbar ist, besteht darin, Code aus den IDL-Deklarationen automatisch zu generieren, Code, der zum Erstellen einer separaten DLL verwendet werden kann, die den Proxy und den Stub implementiert. IDL ist ausreichend reich, um Details der Funktionsargumenttypen und -nutzung zu beschreiben, damit das Marshalling von diesem automatisch generierten Code ausgeführt werden kann. Manchmal sind IDL-Attribute nicht ausreichend, der COM-Autor schreibt dann einen benutzerdefinierten Marshaller. COM lädt diese DLL zur Laufzeit, um die Proxy- und Stub-Objekte automatisch zu erstellen.

  • Spezifisch für die COM-Automatisierungsuntergruppe (IDispatch-Schnittstelle) verfügt Windows über einen integrierten Marshaller, der weiß, wie Aufrufe gebündelt werden, die die Teilmengenanforderungen erfüllen. Sehr gewöhnlich. Es verwendet die Typbibliothek, um die Funktionsdeklaration zu ermitteln.

Die letzten beiden Kugeln erfordern HKLM\Software\Classes\Interface verwenden, es hat Einträge für die IID für jede Schnittstelle. So findet COM heraus, wie der Proxy und der Stub für die Schnittstelle erstellt werden. Wenn es den Schlüssel nicht finden kann, fällt es auf IMarshal zurück. Sie müssen das comInterfaceExternalProxyStub-Element verwenden, um den Registrierungsschlüssel zu ersetzen. Die Verwendung von comInterfaceProxyStub ist ein Sonderfall, bei dem der Proxy- und Stubcode in der COM-Server-Programmdatei enthalten ist, anstatt eine separate Datei zu sein. Eine Option beispielsweise in ATL-Projekten, die mit der Assistentenauswahl "Zusammenführung von Proxy/Stub zulassen" aktiviert wurde.

Das letzte Aufzählungszeichen erfordert außerdem die Verwendung des typelib-Elements, das erforderlich ist, damit der integrierte Marshaller die erforderliche Typbibliothek finden kann. Die ProgId ist erforderlich, wenn der COM-Client eine späte Bindung über IDispatch verwendet, die CreateObject() - Hilfsfunktion in der Laufzeit-Unterstützungsbibliothek des Clients ist buileplate.

Wird beispielsweise in einem beliebigen Skript-Host verwendet.

Mit ein paar Insiderwissen, wie der COM-Server erstellt wurde, hilft sicherlich, kontaktieren Sie immer den Hersteller oder Autor um Rat. Es kann jedoch reverse-engineered werden, indem man beobachtet, welche Registrierungsschlüssel geschrieben werden, wenn der Server registriert wird, das ProcMon-Tool von SysInternals ist der beste Weg, dies zu erkennen. Grundlegende Dinge suchen:

  • Wenn Sie den HKLM\Software\Classes\Interface Schlüssel siehe schreiben, dann können Sie davon ausgehen, dass Sie die comInterface bereitstellen muss | Externe | ProxyStub Element

  • Wenn Sie es schreiben siehe {00.020.420-0.000 -0000-C000-000000000046} für den Schlüssel ProxyStubClsid32, dann können Sie davon ausgehen, dass der Standard-Marshaller verwendet wird und Sie das comInterfaceExternalProxyStub-Element sowie das typelib-Element verwenden müssen. Sie sollten dann sehen, dass es den TypLib-Registrierungsschlüssel des IIDs sowie den Eintrag im Registrierungsschlüssel HKLM \ Software \ Classes \ Typelib schreibt. Letzterer gibt den Pfad der Typbibliothek an. Fast immer gleich wie der COM-Server, ist das Einbetten der Typbibliothek als Ressource sehr üblich. Wenn es separat ist (eine TLB-Datei), müssen Sie es bereitstellen.

  • Wenn der Schlüsselwert ProxyStubClsid32 eine andere GUID ist, können Sie davon ausgehen, dass er eine eigene Proxy/Stub-DLL verwendet. Sie sollten dann auch sehen, dass es den CLSID-Schlüssel für den Proxy schreibt, sein InProcServer32-Schlüssel gibt Ihnen den Pfad zur DLL. Wenn dieser Dateiname mit dem Dateinamen des Servers übereinstimmt, können Sie davon ausgehen, dass der Proxy/Stub-Code zusammengeführt wurde und Sie stattdessen das comInterfaceProxyStub-Element verwenden müssen. Wenn nicht, dann ist comInterfaceExternalProxyStub erforderlich und Sie müssen die DLL bereitstellen

  • Wenn Sie sehen, schreiben Sie die ProgID in dann verwenden Sie das Progid-Element, genau wie in der Ablaufverfolgung gezeigt.

+0

Erstaunlich. Vielen Dank. :-) pdm.dll ist ein interessanter Fall, in dem es eine zweite DLL gibt, msdbg2.dll, die anscheinend * ProxyStuds für die Debugging-Schnittstellen enthält. (msdbg2.dll wird beispielsweise von Visual Studio benötigt, um an einen Prozess anhängen zu können). Die Art und Weise, wie wir pdm.dll verwenden (um vbscript zu debuggen), scheint jedoch die ProxStubs von msdbg2.dll nicht zu benötigen Unser Code funktioniert glücklicherweise ohne msdbg2.dll. (Obwohl, wenn registriert, msdbg2.dll wird durch pdm.dll geladen - keine Ahnung, was es genau tut.) Meh. Das ist alles so ein Durcheinander. –