2016-08-01 28 views
0

Ich habe einige DLLs wie dies angeordnet habe:Kann ich separate DLLs erhalten, um ihre importierten DLLs getrennt aufzulösen?

  • lib.dll - 3rd-Party-DLL mit einer Importbibliothek, die Sie verlinken auf
  • plugin.dll - eine DLL, die entworfen, um lib.dll, ein Plugin Links zu ladende in ein Host-Programm mit LoadLibrary
  • other\plugin.dll - otherplugin Kopie von lib.dll
  • - einem anderen Plugin-DLL, die
  • other\lib.dll-lib.dll Links

(Dies sind nur gewöhnliche DLLs mit einigen exportierten Funktionen - ich bin mit COM oder irgendetwas nicht.)

In meinem Test-Setup, wenn ich LoadLibrary verwenden plugin.dll, zu laden und LoadLibrary dann other\plugin.dll zu laden verwenden Es scheint, dass beide die gleiche geladene Kopie von lib.dll teilen. Aber ich brauche tatsächlich other\plugin.dll zu laden other\lib.dll - Ich möchte nicht die Bibliotheken geteilt werden.

Kann ich das tun? (Idealerweise ohne Neukompilierung lib.dll.)

Antwort

3

Die Technologie, die dies ermöglicht, heißt Application Isolation. Die Funktionsweise besteht darin, dass der Entwickler seine DLLs mithilfe von Manifestdateien in Side-by-Side-Assemblies einordnet.

Lesen Sie Isolated Applications auf MSDN für die offizielle Dokumentation.


Alternativ könnte dies, dass ohne alle arbeiten, vorausgesetzt, Sie sind in der Tat, loading "lib.dll" explizit über LoadLibrary.

Beachten Sie zuerst, dass wenn eine Dll LoadLibrary aufruft, der eigene Ordner der DLL nicht durchsucht wird. Wenn Sie die Dokumentation für LoadLibrary auf MSDN überprüfen, werden Sie feststellen, dass der ausführbare Ordner der Anwendung der bevorzugte Suchpfad ist. Als erstes müssen Sie vor dem Laden von Plugin.dll SetDllDirectory aufrufen, damit es seine eigene Kopie von "lib.dll" finden kann.

Weiter - beachten Sie, dass die LoadLibrary Suchpfade nur verwendet werden, wenn ein relativer Pfad übergeben wird.

Also, wenn Sie FIRST reparieren das DllDirectory und LoadLibrary "Plugin.dll" DANN Call LoadLibrary, übergibt den voll qualifizierten Pfad zu Ihrer eigenen Kopie von Lib.dll, dann plugin.dll wird seine eigene Version mit dem Suchpfad laden und Ihre App lädt explizit ihre eigene Version.

+0

'lib.dll' wird implizit über die Importbibliothek geladen. –

+0

Nun, möglicherweise stecken Sie "plugin.dll" in einer privaten Assembly nebeneinander oder verwenden die Aktivierungskontext-API, um die Load der plugin.dll in einem anderen Aktivierungskontext einzubinden. Ich habe viele Antworten auf diese Art von Fragen, aber alle 5 Jahre alt und ich bin gerade jetzt mein Wissen zu diesem Thema ist so abgestanden, dass sie mich alle verwirren: P –

+1

Gefunden eins: http://StackOverflow.com/Questions/3832290/Ändern-Dll-Suchpfad-für-statisch-verbunden-dll/3832428 # 3832428 –

0

Es gibt eine andere Option: Legen Sie die DLL so fest, dass sie verzögert geladen wird, und verwenden Sie the delay load DLL import hook, um die gewünschte DLL explizit zu laden.

Wenn es darum geht, eine verzögerungsgeladene DLL aufzulösen, wird normalerweise das System (obwohl ich nicht sicher bin, welcher Teil - vermutlich die CRT?) Feststellen, dass bereits ein plugin.dll geladen ist und einen anderen Handle austeilen. Aber mit der Verzögerung laden DLL-Hook können Sie es erhalten, um eine andere DLL mit LoadLibrary laden - in diesem Fall die Plugin-spezifische Kopie der freigegebenen DLL. Geben Sie den vollständigen Pfad an, sodass keine Möglichkeit besteht, dass LoadLibrary einen Punkt an die vorhandene DLL zurückgibt.

Speichern Sie dazu die HINSTANCE der DLL in DllMain.

static HINSTANCE g_hinstDLL; 

BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { 
    if (fdwReason == DLL_PROCESS_ATTACH) 
     g_hinstDLL = hinstDLL; 

    return TRUE; 
} 

Und haben eine geeignete Verzögerung Last Haken, der für.

static FARPROC WINAPI DliHook(unsigned dliNotify, PDelayLoadInfo pdli) { 
    if (dliNotify == dliNotePreLoadLibrary) { 
     if (strcmp(pdli->szDll, "plugin.dll") == 0) { 
      char path[MAX_PATH]; 
      GetModuleFileNameA(g_hinstDLL, path, sizeof path); 
      PathRemoveFileSpecA(path); 
      PathAppendA(path, "plugin.dll"); 

      HMODULE hModule = LoadLibraryA(path); 
      return (FARPROC)hModule; 
     } 
    } 

    return 0; 
} 

const PfnDliHook __pfnDliNotifyHook2 = &DliHook; 

(Am Ende hatte ich auf diesem ganzen Ansatz aufgeben - lib.dll wäre es einmal pro Prozess sein, anzunehmen, schien immer nur geladen, nicht unangemessen, und im Widerspruch mit mir selbst auf verschiedene Weise, wenn sie mehrmals geladen. Wahrscheinlich prinzipiell lösbar, aber ich würde dann wohl nur noch für Linux und OS X dasselbe machen ...)