从非托管c ++动态加载混合模式C ++ / CLI .dll(和依赖项)

时间:2011-08-10 19:33:12

标签: .net c++ c++-cli managed-c++ loadlibrary

我有一个托管C ++程序集,我通过标准的LoadLibrary()调用在非托管c ++应用程序中动态加载。托管C ++程序集依赖于几个托管(C#)程序集。一切正常,直到我将所有托管程序集移动到unmananged应用程序的子目录。举例说明:

  • 托管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其依赖项存在于子目录中?它是一个在非托管应用程序内部运行的库,所以我认为我不能在app.config或其他任何东西中指定它?

2 个答案:

答案 0 :(得分:8)

我认为您正在寻找的是自定义装配解析器。我不得不使用一个来做我认为你想做的事情 - 我想在一个文件夹中找到一些DLL,这个文件夹不在最初的非托管DLL(最终加载托管代码)的树中。

步骤1是创建一个可以调用以设置解析器的功能:

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

然后是解析器。这个例子有一个全局的myFinalPath,在你的情况下是你正在使用的额外文件夹:

/// <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;
}

答案 1 :(得分:5)

在这种情况下,CLR以不寻常的方式加载,通过编译器在编译__declspec(dllexport)的本机导出时注入的thunk。这样做很好,它不是特别快。

CLR将寻找.config文件以初始化主AppDomain。并且将查找MyCoolApp.exe.config,无论这根本不是托管可执行文件。您可以使用<probing> element添加子目录来搜索程序集。