Problem mit LoadLibrary() und Manifest
-
Hallo zusammen!
Zuerst eine kleine Anmerkung: ich kämpfe schon seit zwei Tagen mit dem Problem, habe mich durch etliche Internetseiten gegoogelt und auch in der MSDN-Library gelesen aber habe noch keinen Erfolg gehabt. Auch den Thread http://www.c-plusplus.net/forum/viewtopic-var-t-is-181577-and-highlight-is-.html hab ich gelesen.
Es geht um folgendes: ich arbeite gerade an einem kleinen Tool was die Konfiguration von SimConnect http://msdn.microsoft.com/en-us/library/cc526983.aspx im Netzwerk erleichtern soll. Nix aufregendes aber viele FSX-User kommen nicht so ganz mit den verschiedenen Konfigurationsdateien klar. Dem will ich Abhilfe schaffen.
Problem: für den FSX existieren 3 verschiedene SimConnect Versionen (RTM, SP1 und SP2). Die jeweiligen DLLs liegen im WinSxS Verzeichnis. Für meine Anwendung habe ich ebenfalls 3 DLLs, in jeder davon will ich die jeweilige SimConnect.dll laden. Und genau da liegt das Problem.
Um dem Linker mitzuteilen welche Version der DLL benötigt wird enthält die jeweilige SimConnect.h eine
#pragma commentDirektive. Beispiel für die SP2-Version:
#pragma comment(linker,"/manifestdependency:\"type='win32' " \ "name='" "Microsoft.FlightSimulator.SimConnect" "' " \ "version='" "10.0.61259.0" "' " \ "processorArchitecture='x86' " \ "publicKeyToken='" "67c7c14424d61b5b" "'\"")Der Abschnitt im Manifest sieht folglich so aus:
<dependency>
<dependentAssembly>
<assemblyIdentity type="win32" name="Microsoft.FlightSimulator.SimConnect" version="10.0.61259.0" processorArchitecture="x86" publicKeyToken="67c7c14424d61b5b"></assemblyIdentity>
</dependentAssembly>
</dependency>Die Manifeste sind in die DLLs eingebettet, ich habe das mehrfach überprüft. Aber der Aufruf von
LoadLibrary(L"SimConnect.dll");schlägt fehlt.
GetLastError()gibt den Wert 126 ("The system could not find the module specified").
Steht aber die Assembly-dependency auch im Manifest für die .exe meines Programmes klappt alles wunderbar. Wenn nicht (hab auch versucht in der exe auf das Manifest komplett zu verzichten) klappt es nicht. Das wäre ja nicht das Problem, nur kann ich im Manifest für die .exe nicht die dependency für alle drei Versionen unterbringen (ich hab das versucht aber dann startet das Programm nicht).
Wenn ich aber in jeder meine eigenen DLL eine SimConnect-Funktion aufrufe dann wird die entsprechende SimConnect.dll in der richtigen Version geladen. Nur mit LoadLibrary() klappt es nicht.
Zwar hab ich eine Fehlerbehandlung in meinem Programm für den Fall das was schiefgeht beim Laden der DLLs. Aber mir geht es hauptsächlich um die Frage warum
LoadLibrary()trotz embedded Manifest fehlschlägt wenn die dependency nicht im Manifest der .exe steht. Es ist für die Zukunft meines Tools nicht zwingend das das so funktioniert wie ich möchte (wäre aber schön). Wenn es also keine Lösung für das Problem gibt würde ich gern verstehen warum das so nicht geht.
Viele Grüße
Sven
-
Einige Anmerkungen:
- Was steht denn im EventLog genauz für einen Fehler?
- Das Embedded Manifest der DLL hat hoffentlich die ID 2!
- Versuche mal LoadLibraryEx
-
Jochen Kalmbach schrieb:
Einige Anmerkungen:
- Was steht denn im EventLog genauz für einen Fehler?Muss ich mal schauen (bin nicht daheim, Freundin muß erst TeamViewer auf meinem Rechner installieren
).Jochen Kalmbach schrieb:
- Das Embedded Manifest der DLL hat hoffentlich die ID 2!
Ja, hat es.
Jochen Kalmbach schrieb:
- Versuche mal LoadLibraryEx
Hab ich versucht, klappt leider auch nicht, hab sogar mit DONT_RESOLVE_DLL_REFERENCES (falls die zu ladende SimConnect.dll ihrerseits Dlls nicht findet).
-
Falls Du Vista hast, könntest Du auch mit LogMan mehr rausfinden
http://msdn.microsoft.com/de-de/magazine/cc163437.aspx
-
Jochen Kalmbach schrieb:
Falls Du Vista hast, könntest Du auch mit LogMan mehr rausfinden
http://msdn.microsoft.com/de-de/magazine/cc163437.aspxDanke für den Hinweis, benutze Vista Business 64Bit.Werd ich mir dann anschauen wenn ich zu Hause bin, per Fernwartung ist das nicht so toll

-
So, ich habe noch mal durchgetestet:
Eintrag der dependency in .exe und .dll -> LoadLibrary() klappt
Eintrag der dependency nur in .exe -> LoadLibrary() klappt
Eintrag der dependency nur in .dll -> LoadLibrary() klappt nicht
Den Eintrag im Manifest der dll kann ich mit
#define SIMCONNECT_H_NOMANIFESTunterbinden. Die oben erwaehnte #pragma - Anweisung verwende ich dann im Header fuer die .exe und hab den Eintrag dann in deren Manifest. Wenn ich #pragma Anweisungen der verschiedenen Versionen in den Header der .exe packe startet das Programm natuerlich nicht. Auszug aus dem EventLog ( = Fehlermeldung beim Programmstart):
Activation context generation failed for "c:\Users\Sven\Documents\Visual Studio 2008\Projects\SimConnectConfig\Debug\SimConnectConfig.exe".Error in manifest or policy file "" on line . A component version required by the application conflicts with another component version already active. Conflicting components are:. Component 1: C:\Windows\WinSxS\manifests\x86_microsoft.flightsimulator.simconnect_67c7c14424d61b5b_10.0.61242.0_none_e079b46b85043c20.manifest. Component 2: C:\Windows\WinSxS\manifests\x86_microsoft.flightsimulator.simconnect_67c7c14424d61b5b_10.0.60905.0_none_dd92b94d8a196297.manifest.
Lasse ich
#define SIMCONNECT_H_NOMANIFESTweg und der Linker-Comment geht an die DLLs stehen in den beiden DLL-Manifesten auch die beiden verschiedenen dependencys drin. In der .exe nur die erste die sie findet (Da ja
#define _SIMCONNECT_H_schon definiert ist wird die zweite Version ja ignoriert). Allerdings wird die zweite Version der SimConnect.dll geladen wenn ich eine Funktion dieser aufrufe (es sind dann also beide Versionen im Speicher).
Vermutlich kann ich das nur loesen indem ich die Abhaengigkeiten des .exe Projekts von den DLL-Projekten entferne. Da ich in den DLL aber auch Klassen exportiere braeuchte ich wieder zusaetzliche statische Bibliotheken. Das hab ich gestern schon versucht, bekam aber immer Linker-Fehler wegen Konflikten mit der CRT (obwohl alle Projekte die gleichen Runtime-Librarys benutzt haben).
Fuer die GetLastError() Fehler "The specified module could not be found." gibt es uebrigens keine Eintraege im EventLog.
Werd mich nochmal daran versuchen fuer meine DLLs auch statische Libs zu erzeugen gegen die ich mit dem .exe Projekt linken kann. Vielleicht bringt mich das ein Stueck weiter.