COM aus .Net verwenden

COM wurde entwickelt, um ein einheitliches Zugriffsmodell über verschiedene Programmiersprachen hinweg zur Verfügung zu stellen. Das System mag nicht perfekt sein, funktioniert aber in der Regel.

Probleme mit COM aus .Net

Leider hat Microsoft sich für einen anderen Weg entschieden, wenn man auf .Net-Assemblies per COM-Interop aus anderen .Net-Assemblies zugreifen möchte. Sie können keinen COM-Verweis hinzufügen und werden stattdessen gezwungen, einen Assemblyverweis einzufügen. Das kann in vielen Fällen funktionieren, aber oft genug tut es das nicht. Wie sich zeigt, funktioniert es nicht bei PDFCreator.

PDFCreator erfordert, dass verschiedene Dateien im dem Ordner mit den ausführbaren Dateien vorhanden sind (Hilfsanwendungen, native Bibliotheken etc.). Wenn Sie einen Assemblyverweis aus Ihrem Projekt erstellen, werden diese Dateien in Ihr Buildverzeichnis kopiert und damit vom Rest von PDFCreator abgeschnitten. Das führt zu Fehlern, z.B. dass PDFCreator.exe oder Ghostscript nicht gefunden werden kann.

Wir wissen nicht, warum Microsoft sich so entschieden hat. Da das Verhalten aber seit der ersten Version von COM in .Net so ist, wird es höchstwahrscheinlich so bleiben und wir müssen uns damit arrangieren.

Vermeiden der Probleme mit Late Binding

Glücklicherweise kann man in .Net die Erkennung von .Net-Assemblies austricksen, indem Late Binding verwendet wird.

Als erstes müssen Sie sich den Typ über die ProgID von PDFCreator holen. Danach können Sie eine Instanz dieses Types mithilfe des Activators erzeugen. Anschließend können Sie alle Methoden der COM-Schnittstelle verwenden.

Type queueType = Type.GetTypeFromProgID("PDFCreator.JobQueue");
dynamic queue = Activator.CreateInstance(queueType);

queue.Initialize();
// add more logic here

Der Nachteil daran ist, dass Sie die Unterstützung für IntelliSense verlieren. Sie könnten die Methodensignatures aus der .tlb-Datei erhalten, die erzeugt wird, wenn die COM-Schnittstelle registriert wird. Das wird von Microsoft aber wiederum unterbunden.

Mit PDFCreator 2.5.3 haben wir deshalb einen Wrapper erstellt, der dieselben Klassen und Methoden zur Verfügung stellt wie die eigentliche COM-Schnittstelle, diese aber mithilfe des dynamischen Typs aufruft. Sie müssen dazu die Datei PDFCreator.ComWrapper.dll aus dem Installationsverzeichnis von PDFCreator referenzieren. Diese Datei wird dann in Ihren Build-Ordner kopiert, hat aber selbst keine Abhängigkeiten. Sie können diese Datei auch für verschiedene Versionen von PDFCreator verwenden, da sich die COM-Schnittstelle nicht ändert. Wir empfehlen Ihnen trotzdem, die Datei von Zeit zu Zeit zu aktualisieren (z.B. Ihre Anwendung neu zu kompilieren).

In einigen Fällen haben wir festgestellt, dass .Net erkennt, dass wir die Erkennung für .Net und COM umgehen möchten, wodurch dieselben Fehlermeldungen entstanden („PDFCreator.exe kann nicht gefunden werden“), die bei der direkten Verwendung der .Net-Assembly auftreten. In dem Fall müssen Sie den dynamischen Typ in Ihrem Code einmal instanzieren. Danach funktioniert der COM-Wrapper ohne Probleme.

Type queueType = Type.GetTypeFromProgID("PDFCreator.JobQueue");
Activator.CreateInstance(queueType);