【问题标题】:Mixed Assembly Not Discovering Native DLLs混合程序集未发现本机 DLL
【发布时间】:2013-07-15 07:05:58
【问题描述】:

我有一个带有本机 dll 依赖项的混合模式 dll。

我正在使用 Assembly.Load 从 C# exe 加载混合模式 dll。但是,混合模式 dll 的位置不在应用程序 bin 目录中,因此它会失败,因为它只在 bin 中查找本机 C++ dll 和 PATH 环境变量中的文件夹。

我认为使用选项 /assemblylinkresource 可以阻止此操作并强制在部署的混合模式 dll 旁边的备用目录中找到本机 dll。事实证明这是不正确的。

有没有办法使用现有的 C++/CLI 混合模式 dll 创建带有本机 dll 的多文件程序集?我见过的唯一示例 (http://msdn.microsoft.com/en-us/library/xawyf94k(v=vs.100).aspx) 是使用 .netmodules 与本机 dll 结合。

因此,解决方案是:

a) 一些如何强制应用程序在您选择的目录中搜索本机依赖项;要么 b) 将本机 dll 打包到一个托管的混合模式程序集中(这甚至可能吗??) - 给定静态链接依赖项不是一种选择。

【问题讨论】:

    标签: c# c++ interop c++-cli


    【解决方案1】:

    应用正常的 Windows DLL 搜索规则。所以是的,没有希望它会找到那些 DLL。 “多文件程序集”也不起作用,您无法合并本机代码。您拥有的选项,大致按首选顺序:

    • 调用SetDllDirectory() 将包含DLL 的路径添加到Windows 将查找的目录集中。如果外部代码也使用它,可能会失败。
    • 使用 Environment.SetEnvironmentVariable() 将路径附加到 PATH 环境变量。这只会更改 PATH 的进程副本,因此是一种合理的方法。在 PATH 已达到限制的臃肿机器上可能会失败。
    • 将 Enviroment.CurrentDirectory 设置为包含 DLL 的路径。如果外部代码也修改它,可能会失败。
    • 在 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\KnownDLLs 注册表项中记录每个 DLL 安装时的路径。
    • 在 Windows 并行缓存中安装 DLL,并使用清单将其告知 Windows。这很难做到。

    【讨论】:

    • 非常感谢!在您的第一个解决方案中,“如果外部代码也使用它可能会失败”是什么意思? SetDllDirectory 文档msdn.microsoft.com/en-us/library/ms686203%28v=vs.85%29.aspx 声明“将目录添加到用于定位应用程序 DLL 的搜索路径”。所以即使外部代码使用它——它不会只是为搜索添加一个额外的路径吗?
    • 感谢第四个解决方案。但在我们的特定情况下,这不是一个选项,因为它是一个自举应用程序,并且在安装 bootstr 应用程序时实现是未知的(dll 依赖项)。
    • 否,如文档所述:“每次调用 SetDllDirectory 函数时,它都会替换在之前的 SetDllDirectory 调用中指定的目录。” AddDllDirectory() 更好,但它是 Windows 的一个非常晚的添加。
    • 如果 PATH 环境变量膨胀,我想我会使用选项 2 并回退选项 1。
    【解决方案2】:

    未使用 MMA 测试的潜在候选解决方案:这可能不是您希望的最佳解决方案,但我想我会添加它,因为它可以帮助您实现解决方案 a)。在 c++ 中,您可以通过使用 SetDllDirectory 手动设置要搜索的目录(仅适用于 XP SP1)或使用 LoadLibraryEx 手动加载 dll 来控制加载路径和 path search order

    我想可以使用P/invokes 在 C# 中访问这些调用

    [DllImport("kernel32.dll", CharSet=CharSet.Auto)]
    private static extern void SetDllDirectory(string lpPathName);
    

    【讨论】:

    • 这可行。所以我使用 Ninject 进行后期绑定 - 所以我所要做的就是在调用 _kernel.Get<IMixedModeExample> 之前调用 SetDllDirectory
    • 我认为您在编辑中提供的链接不适用于本机 dll 依赖项。
    • @Seth:试试吧,我认为在进行 p/invoke 调用之前,SetDllDirectoryLoadLibrary 应该可以工作。
    • @Seth:抱歉,我觉得我的解决方案有点笨拙和不确定,并开始寻找更好的解决方案,(并且错过了该链接不适用于本机 DLL;现在将其删除。)跨度>
    • @BenVoigt 指的是一个现已被删除的链接。
    猜你喜欢
    • 1970-01-01
    • 2011-03-20
    • 2010-12-13
    • 2013-07-22
    • 1970-01-01
    • 2014-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多