DLLs in einem anderen Ordner referenzieren
-
Hallo,
mich würde interessieren, ob es eine Möglichkeit gibt, DLLs, die durch eine
mitgelinkte lib-Datei eingebunden werden, in einem anderen Ordner aufzubewahren,
als in dem, indem sich die Hauptanwendung befindet.
Normalerweise macht das Programm dann Zicken, weil es die DLL nicht findet.
Ich möchte z.b. einen unterordner "bin\" haben, in dem alle möglichen benötigten
DLLs liegen, und die Hauptanwendung soll ein Verzeichnis höher liegen.
Gibt es da ne Möglichkeit, meinen Libs zu sagen, sie sollen die DLL nicht im
Hauptordner, sondern in "bin\" suchen?
-
AFAIK geht das nicht und du musst mit der dynamischen Variante um LoadLibrary und GetProcAddress arbeiten.
Die Suche nach den benötigten DLLs läuft ja über Windows. Die libs sagen nur, WAS eingebunden wird, nicht WO das ist. Windows muss die DLLs finden. Dazu wird soweit ich weiß zunächst das Programmverzeichnis, dann windows\system32 und dann der komplette PATH abgearbeitet. Wenn da nichts gefunden wird, kommt der Fehler.
Alternativ könntest du dein bin-Verzeichnis in PATH eintragen, aber ob das der Weisheit letzter Schluß ist, glaube ich nicht.
gruß
-
Das ist ab Windows XP möglich, wenn Du ein entsprechendes Manifest erzeugst...
Dann funktioniert das auch für das implizite Laden einer DLL.
-
Theoretisch mit
<runtime> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <probing privatePath="bin"/> </assemblyBinding> </runtime>
-
Interessant, interessant.
Gibt es eigentlich irgendwo eine nette Einführung in das Thema "Manifests bei XP und Vista" ? Bisher bin ich immer um die Dinger rumgekommen bzw. hab den Compiler das nötige erledigen lassen, aber scheinbar sind sie doch nützlich
-
Hab ein bisschen gegoogelt und es scheint, als wenn der Trick mit
<probing privatePath="bin" />
nur für .NET klappt. Bin laufend auf Forenbeitrage über C#
gestoßen. Hab versucht, eine Manifestdatei einzubinden, aber das Programm ist
danach nicht mehr lauffähig und der Compiler warnt mich:
Unrecognized Element "configuration" in namespace "urn:schemas-microsoft-com:asm.v1".
Meine Manifest-Datei sieht so aus:<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> <configuration> <runtime> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <probing privatePath="bin"/> </assemblyBinding> </runtime> </configuration> </assembly>
Hab ich da einfach was falsch gemacht oder gehts doch nicht?
@mad_martin: Wie kann ich denn meinen Lib-Dateien per LoadLibrary das
Handle auf die DLL übergeben? Dann wärs ja kein Problem, einfach ein anderes
Verzeichnis zu benutzen.
-
-
@Norman:
HMODULE myDLL = LoadLibrary("bin\myDll.dll");
Sollte so funktionieren!
-
Neee, das funktioniert nicht, wenn man gegen die Import-LIB der DLL gelinkt hat...
-
Achso, hast Recht. Ich hab auch die Frage scheinbar nicht richtig gelesen.
Also, Norman:
Es gibt 2 Möglichkeiten, Funktionen aus DLLs in einem Programm verfügbar zu machen. Entweder statisches Linken der libs in das Programm oder die dynamische Anbindung per LoadLibrary und GetProcAddress. In ersterem Fall bringt die lib die nötigen Einsprungadressen für die DLL mit. Der Linker packt das ganze dann so zusammen, dass die Funktionen direkt im Programm (Header vorausgesetzt) verfügbar sind. Im zweiten Fall werden keinerlei Einsprungadressen in das Programm mit eingebunden. Dafür werden diese Adressen aus einer DLL ausgelesen. Das macht das OS mit der Funktion GetProcAddress, die einer eigenen, deklarierten, aber nicht definierten Funktion eine Adresse innerhalb der DLL zuweist, die auf die wirkliche Funktion verweist. Vorteil hier ist z.B. die umfangreichere Fehlerbehandlung, d.h. das System wirft nicht einfach einen Fehler wegen der fehlenden DLL (wie im statischen Fall), sondern dein Programm kann eine ganz eigene Fehlermeldung senden, wenn die Funktionen GetProcAddress und LoadLibrary keine Adresse bzw. DLL finden. Auch lassen sich so sehr leicht Plugin-System realisieren, in dem die Plugins einfach als DLLs mit passenden Schnittstellen in ein "plugins" Verzeichnis gelegt werden und direkt im Programm verfügbar sind, sobald ein Suchalgorithmus alle Dateien mit passender Schnittstelle gefunden und gelistet hat.AFAIK kann man beide Wege nicht mit der selben DLL verwenden, ganz sicher bin ich mir nicht. Man kanns natürlich bei mehreren DLLs mixen, kommt auf die Situation an, ob das sinnvoll ist (siehe Pluginsystem).
Die beiden Wege werden grundsätzlich hier und hier mit Codebeispielen erläutert.
gruß
Martin
-
Danke für die vielen Antworten. Die beiden Wege, die DLL in mein Programm
einzubinden, waren mir klar. Die Sache ist halt, dass es eine Library ist,
die mir "von außen" zur Verfügung gestellt wird und die ich nur statisch
über eine lib- und Headerdatei linken kann.
Scheinbar ist es aber nicht ganz so einfach, in diesem Fall den Ordner zu
wechseln. Ist aber auch nicht so schlimm, dann muss ich halt alle Dateien im
selben Ordner lassen, war nur eine Frage, ob das mit einfach Mitteln möglich
ist.
Danke nochmal!Gruss,
Norman0406
-
Was meinst du mit "von außen" und warum musst du die dann statisch linken?
Du hast doch die Headerdatei, also auch die Exports. Daran kannst du dich orientieren und die DLL dynamisch laden.