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

Jor*_*Day 5 .net c++ managed-c++ c++-cli 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或其他任何东西中指定它?

Ed *_*tes 8

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

第1步是创建一个可以调用以设置解析器的函数:

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

然后是解析器.这个例子有一个全局的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;
}
Run Code Online (Sandbox Code Playgroud)


Han*_*ant 6

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

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