2011-08-10 37 views
5

我有一個託管C++程序集,我通過標準LoadLibrary()調用在非託管C++應用程序中動態加載。託管的C++程序集依賴於多個託管(C#)程序集。一切工作正常,直到我將所有託管程序集移動到非管理應用程序的子目錄中。爲了說明:從非託管C++動態加載混合模式C++/CLI .dll(和依賴關係)

  • 託管C++的.dll(MyCoolDll.dll)

    • 依賴於DotNetDll1.dll
    • 依賴於DotNetDll2.dll
  • 不受管理的C++應用程式(MyCoolApp .exe)

    • 個加載通過調用LoadLibrary MyCoolDll.dll( 「MyCoolDll.dll」)

此工作正常,直到我移動MyCoolDll.dll,DotNetDll1.dll & DotNetDll2.dll到/ someSubDirectory(在MyCoolApp的代碼。 exe文件已更新到LoadLibrary(「someSubDirectory/MyCooldll.dll」)

我在猜測MyCoolDll.dll加載時,它試圖找到DotNetDll1.dll和DotNetDll2.dll在工作目錄中,而不是目錄中它住進去。

我該如何告訴MyCoolDll.dll它的依賴關係存在於一個子目錄中ectory?它是一個運行在非託管應用程序內部的庫,所以我不認爲我可以在app.config或其他任何東西中指定它?

+1

哇,漢斯,工作!由於MyCoolApp.exe只是一個普通的舊的Win32應用程序(不是.NET),所以我真的很懷疑,所以我想爲它添加一個應用程序配置文件是無濟於事的。謝謝!你是否想把它寫成答案而不是評論,我會將其標記爲已接受? – Jordan0Day

回答

5

的CLR被加載在這種情況下一個不尋常的方式,通過一個thunk編譯器編譯本地出口注射時爲__declspec(dllexport)。這樣做很好,它不是特別快。

CLR將出去尋找.config文件來初始化主AppDomain。並且會查找MyCoolApp.exe.config,無論這根本不是託管可執行文件。您可以使用<probing> element添加子目錄來搜索程序集。

8

我認爲你要找的是一個自定義程序集解析器。我不得不用一個來做我認爲你正在嘗試做的事情 - 我想找到一些不在最初的非託管DLL(最終加載託管代碼)的樹中的文件夾中找到一些DLL。

第1步是使一個函數可以調用來設置解析器:

void PrepareManagedCode() 
{ 
    // Set up our resolver for assembly loading 
    AppDomain^ currentDomain = AppDomain::CurrentDomain; 
    currentDomain->AssemblyResolve += gcnew ResolveEventHandler(currentDomain_AssemblyResolve); 
} // PrepareManagedCode() 

則解決。這個例子有一個全球性的ourFinalPath這將在你的情況是你使用額外的文件夾:

/// <summary> 
/// This handler is called only when the CLR tries to bind to the assembly and fails 
/// </summary> 
/// <param name="sender">Event originator</param> 
/// <param name="args">Event data</param> 
/// <returns>The loaded assembly</returns> 
Assembly^ currentDomain_AssemblyResolve(Object^ sender, ResolveEventArgs^ args) 
{ 
    sender; 

    // If this is an mscorlib, do a bare load 
    if (args->Name->Length >= 8 && args->Name->Substring(0, 8) == L"mscorlib") 
    { 
     return Assembly::Load(args->Name->Substring(0, args->Name->IndexOf(L",")) + L".dll"); 
    } 

    // Load the assembly from the specified path 
    String^ finalPath = nullptr; 
    try 
    { 
     finalPath = gcnew String(ourAssemblyPath) + args->Name->Substring(0, args->Name->IndexOf(",")) + ".dll"; 
     Assembly^ retval = Assembly::LoadFrom(finalPath); 
     return retval; 
    } 
    catch (...) 
    { 
    } 

    return nullptr; 
} 
+0

這是我認爲我必須走下去的路徑 - 問題似乎是我仍然需要在主應用程序目錄中有MyCoolDll.dll的依賴關係,因爲.net在之前不會搜索子文件夾甚至加載了MyCoolDll。dll(所以程序集解析器不會先建立)。令我驚訝的是,上述漢斯的建議工作(即使MyCoolApp.exe不是託管可執行文件)。 – Jordan0Day

+0

在需要程序集解析之前,您的非託管DLL將加載。然後,您可以自己加載混合模式DLL,並調用程序集解析設置。對於複雜場景,你需要它;然而,如果一個簡單的配置文件適用於你的情況,太棒了! –

+0

我看到的問題是我的混合模式DLL有一些其他.NET程序集的依賴關係 - 所以除非我將這些依賴項放在主目錄而不是子文件夾中,否則我將無法獲取任何可執行代碼我的混合模式DLL,我可以連接一個程序集解析器。 – Jordan0Day