2010-03-09 8 views
10

Ich habe eine vorhandene App, die P/ruft auf eine DLL im selben Verzeichnis wie die App selbst auf.P/Aufrufen dynamischer DLL-Suchpfad

Jetzt (aufgrund der Tatsache, dass Canon eine der Crappiest APIs produziert) muss ich zwei Versionen dieser API unterstützen und zur Laufzeit bestimmen, welche ich verwenden soll (alt oder neu). Da die DLLs den gleichen Namen haben (der erste lädt andere DLLs mit gleichen Namen, so dass nur die Umbenennung der ersten nicht hilft), muss ich sie in verschiedenen Verzeichnissen behalten.

Daher meine Frage: Welche Optionen habe ich zu steuern, welches Verzeichnis die DLL in einer DllImport-Deklaration verwendet verwendet?

Ich denke, ich versuche, eine dieser beiden Ideen beginnen können:

1) Verwenden Sie „SetDllDirectory“ meine gewünschte Verzeichnis zu setzen, bevor die erste P/Invoke tun und es dann anschließend zurückgesetzt.

2) Laden Sie die gewünschte DLL manuell mit "LoadLibraryEx" und hoffe, dass das den Trick macht.

Aber gibt es noch mehr ". NET: ish way" zuerst ausprobieren?

UPDATE: Ich realisiere, dass ich alle Zugriffe auf die DLLs in zwei separaten .Net Assemblies stopfen kann und dann jedes einzelne davon in einem separaten Verzeichnis mit den entsprechenden API-Dateien ablegen kann. Dann kann ich die richtige .Net-Assembly dynamisch laden und das Laden der richtigen DLL wird automatisch geschehen. Irgendein Grund, der nicht funktionieren sollte?

Ich kann mir eins vorstellen: Wie würde ich über Debugging dieses Zeug gehen? Es ist möglich, Visual Studio mitzuteilen, dass eine Assembly (in meiner Lösung enthalten) in einem Unterverzeichnis platziert und von dort debuggt werden soll?

Antwort

9

Mein Beileid, habe ich eine der APIs gesehen und es war in der Tat erschreckend schlecht. Das größere Problem ist, dass Sie in der Lage sein müssen, Windows zu überzeugen, die DLL zu finden. Sie befinden sich nicht in Ihrem .exe-Verzeichnis, so dass der Standard nicht funktioniert. Die Verwendung von SetDllDirectory() würde funktionieren, auch mit Environment.CurrentDirectory. LoadLibrary kann nicht funktionieren, der P/Invoke-Marshaller wird LoadLibrary selbst verwenden.

Wenn es überhaupt eine Option ist, können Sie unterschiedliche Namen für die zwei P/Invoke-Deklarationen verwenden, verschiedene Argumente für den DllImport() - Konstruktor verwenden und das EntryPoint-Attribut verwenden. Klingt nicht so, als würde es fliegen.

+1

Für den Moment gebe ich Ihnen ein +1 für Ihr Beileid, das habe ich wirklich gebraucht, nachdem ich in den letzten sechs Jahren mehrmals mit ihren APIs konfrontiert worden war ... –

1

Ihre erste Option (P/Invoke mit SetDllDirectory) ist die Option, die ich persönlich bevorzuge. Leider gibt es keine ".NETish" -Methode, um native DLLs zu laden ... was sinnvoll ist.

2

Ich denke, die zweite Option wird funktionieren, aber es wird eine Menge Code schreiben müssen, um DLL-Laden in .net verwalten.

Zuerst könnte man auch arbeiten, aber ich mag es entweder nicht.

Hier ist mein Vorschlag: Sie vollständigen Pfad angeben (und kann relativ sein) in DllImport [DllImport(@"C:\dll\a32.dll"]

+0

Das Problem ist das Verzeichnis, in dem die DLL ausgeführt wird, nicht das Laden der DLLs selbst, denke ich. – Tanzelax