Situation:
Eine C++-DLL mit managed und unmanaged Code läuft auf manchen Zielsystemen nicht, es erscheint eine Fehlermeldung:
Could not load file or assembly ‚ZetaHtmlTidy, Version=1.0.3236.15571, Culture=neutral, PublicKeyToken=null‘ or one of its dependencies. Diese Anwendung konnte nicht gestartet werden, weil die Anwenungskonfiguration nicht korrekt ist. Zur Problembehebung sollten Sie die Anwendung neu installieren. (Exception from HRESULT: 0x800736B1)
Dies, obwohl alle Dateien der CRT vorhanden sind:
- Microsoft.VC90.CRT.manifest
- msvcm90.dll
- msvcp90.dll
- msvcr90.dll
Ursache:
In meinem Fall war es so, dass die DLL nicht gegen die neueste Version der CRT gelinkt war. Sie war noch gegen die CRT aus Microsoft Visual Studio 2008 (SP 0) gelinkt, ausgeliefert habe ich aber die CRT-Version von Microsoft Visual Studio 2008, SP 1.
Konkret wurde die Version 9.0.30729.1 der CRT ausgeliefert, in der Manifest-Datei meiner Anwendung stand aber noch die Referenz auf 9.0.21022.8 drin.
Lösung:
Das Projekt neu kompilieren, aber mit der Besonderheit, dass der „/D“-Compiler-Schalter zusätzlich noch den Befehl „_BIND_TO_CURRENT_VCLIBS_VERSION=1“ mitgegeben bekam. Siehe Erklärung hier und hier.
Interessanterweise hatte ich erst Erfolg, als ich den Befehl vor alle anderen Befehle in den Projekt-Optionen schrieb. Also z.B. vor die „NDEBUG“-Präprozessor-Definition.
Außerdem habe ich zur Sicherheit den kompletten Ausgabeordner der zu kompilierenden DLL gelöscht.
Danach neu kompiliert und es hat funktioniert.
Anmerkungen:
Einige Hyperlinks zu guten Erklärungen bzw. Werkzeugen die Hilfreich waren:
- Der bereits oben verlinkte Weblog-Artikel „Binding to the most recent Visual Studio Libraries“ beschreibt ausführlich was zu tun ist. Dort wird auch die Verwendung des Werkzeugs „dumpbin“ beschrieben, was mir hilfreich war.
- Um zu sehen, auf welches CRT-Manifest/-Version tatsächlich in meiner erzeugten DLL verwiesen wird, ist das Werkzeug „Manifest View 1.0“ sehr hilfreich gewesen.
- Ansonsten gibt’s zur Fehlersuche und allgemein zum Deployment von VC++-Anwendungen/-DLLs einiges in der MSDN-Bibliothek.
Ich hoffe der Artikel hier hilft anderen und mir zu einem späteren Zeitpunkt.
Das äh… ja. Ich verstehe C++ einfach nicht – ich meine, ich bin ja auch nur Laie, aber es gibt doch deutlich einfachere Programmiersprachen. Respekt vor all den Leuten, die da nicht nur noch Fragezeichen über dem Kopf haben. Echt! 🙂
Das C++ mache ich auch nur wenn es sein muss. Die Entwicklungszeit geht dadurch, wie dieses Beispiel hier zeigt, deutlich nach oben.
Manchmal muss das aber sein, leider!
Kommentar kommt zwar ein wenig spät, aber ich hoffe, dass es jemandem weiterhilft:
Hab kürzlich unsere ganze Applikations-Suite auf die dynamischen Runtimes (C, C++, MFC) umgestellt und vor der Auslieferung entdeckt, dass per Manifestdatei an eine ältere Version der Runtime gebunden, aber die neuere Runtime dann tatsächlich bei Ausführung der Programme geladen wurde. Recherchen im Internet haben bis jetzt nur Artikel wie diesen hervorgebracht, in denen beschrieben wird, dass das ein großes Problem ist – ist es aber nicht!
Kurzum: Nicht nur die Merge Modules der Runtime ausliefern, sondern auch die Merge Modules für die Policy-Dateien! Die Policy-Dateien leiten Anfragen an ältere Runtimes einfach auf die neueste installierte weiter.
Damit funktioniert folgendes Szenario:
– Entwickelt wird unter VC9 (VS2008) SP1 mit Makro _BIND_TO_CURRENT_VCLIBS=1 (als Präprozessor-Makro sowohl für den C/C++ Compiler als auch für den midl-Compiler definiert). Damit enthält das Manifest unserer Applikationen eine Abhängigkeit auf die Runtime mit Version 9.0.30729.1.
– Da wir eine statische Bibliothek als Drittkomponente verwenden, die wir nicht beeinflussen können, und deren Manifest an die Runtime mit Version 9.0.21022.8 bindet, stehen nun im Manifest unserer Applikationen zwei Abhängigkeiten auf verschiedene Versionen der Runtime.
– Mit unseren Installationspaketen liefere ich die neueste Runtime per Merge Modules aus (und die für die Policy-Dateien), das ist derzeit Version 9.0.30729.4148
Alles funktioniert wie am Schnürchen, so lange die Policy-Dateien vorhanden sind.
Getestet auf frischen Windows Server 2003 und Windows XP Professional Installationen ohne vorhandene WinSxS-Runtime-Assemblies.