gpt4 book ai didi

dll - Win32 App插件如何将其DLL加载到自己的目录中

转载 作者:行者123 更新时间:2023-12-04 23:32:50 24 4
gpt4 key购买 nike

我的代码是特定应用程序的插件,使用 Visual Studio 8 用 C++ 编写。它使用来自外部提供程序的两个 DLL。不幸的是,我的插件无法启动,因为找不到 DLL(我将它们放在与插件本身相同的目录中)。

当我手动将 DLL 移动或复制到主机应用程序目录时,插件加载正常。对于最终用户来说,这种移动被认为是 Not Acceptable 麻烦,我正在寻找一种方法让我的插件透明地加载其 DLL。我能做些什么?

相关细节:

  • 主机应用程序插件位于主机应用程序规定的目录中。该目录不在 DLL 搜索路径中,我无法控制它。
  • 插件本身被打包为插件目录的子目录,包含插件代码本身,以及与插件相关的任何资源(例如图像、配置文件……)。我控制该子目录中的内容,称为“捆绑包”,但不控制它所在的位置。
  • 该应用程序的常见插件安装习惯用法是最终用户将插件包复制到插件目录。

  • 这个插件是插件的 Macintosh 版本的一个端口。在 Mac 上没有问题,因为每个二进制文件都包含自己的动态库搜索路径,我根据需要为我的插件二进制文件设置了它。要在 Mac 上进行设置,只需在 Xcode IDE 中进行项目设置。这就是为什么我希望在 Visual Studio 中有类似的东西,但我找不到任何相关的东西。此外,Visual Studio 的帮助绝非如此,谷歌也没有。

    一个可能的解决方法是让我的代码明确告诉 Windows 在哪里可以找到 DLL,但我不知道如何,而且无论如何,由于我的代码甚至没有启动,它没有机会这样做。

    作为一名 Mac 开发人员,我意识到我可能要求一些非常基本的东西。如果是这样的话,我很抱歉,但我已经没有头发可以拔了。

    最佳答案

    你不是在要求一些非常基本的东西。 Windows 根本不支持你想要的。

    您有一些选项可以解决此问题:

  • 创建两个 DLL。您的插件实现 dll,静态链接到您需要的任何其他 dll。还有一个由托管应用程序加载的简单“外观”dll。外观 dll 调用 SetDllDirectory 然后 LoadLibrary 以使用所需的搜索路径加载您的实现 dll,然后,对于每个插件导出的函数,它实现一个 stub 函数,该函数使用 GetProcAddress 将调用直接传递给您的实现 dll。

  • 如果插件接口(interface)复杂,而你使用的dll接口(interface)不复杂,那么:
  • 放弃并使用 LoadLibrary(带有显式路径)和 GetProcAddress 来访问卫星 dll 中的功能。痛。
  • 最后一个选项是 Windows 程序员记录最少且理解最差的选项。基本上,我们使用为支持 .NET 而构建的技术的 Windows 版本:并排程序集。不要害怕。 “Side by Side 程序集”非常简单,只是一个普通的旧 dll,但附带一个 .manifest 文件,提供有关它的一些额外信息。

  • 我们要这样做的原因是通过 SxS 技术链接的 dll 的搜索顺序与常规 dll 搜索顺序不同:- 即 - 在搜索 c:\windows\WinSxS 后,windows 将搜索与引用dll的dll,而不是exe的文件夹。

    首先清点您的插件 dll 需要链接到的所有卫星 dll,并从中创建一个“程序集”。这意味着:创建一个带有一堆 file= 节点的 .manifest 文件。您需要为程序集命名。让我们称之为“MyAssembly”。

    在您的 dll 文件夹中创建文件“MyAssembly.manifest”,其内容类似于以下内容:(列出您需要包含的每个 dll)
    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
    <assemblyIdentity name="MyAssembly" processorArchitecture="*" type="win32" version="1.0.0.1"/>
    <file name="firstrequireddll.dll"/>
    <file name="2ndrequireddll.dll"/>
    </assembly>

    现在,这就是你的程序集 list 。我们已经完成了一半。

    下半部分是实际让您的 dll 使用程序集,为此您需要将 list 资源添加到您的 Dll 文件中。该 list 最终需要包含以下内容:-
    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
    <dependency>
    <dependentAssembly>
    <assemblyIdentity type="win32" name="MyAssembly" version="1.0.0.1" processorArchitecture="*"/>
    </dependentAssembly>
    </dependency>
    </assembly>

    显然,应用程序 list (当嵌入到 dll 中时这是一个令人困惑的名称),也允许使用 <file>节点,因此可以跳过创建程序集,直接使用
    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
    <file name="firstrequireddll.dll"/>
    <file name="2ndrequireddll.dll"/>
    </assembly>

    作为 dll 的 list 。我还没有玩弄那个迭代,所以我不确定它如何改变正常的 dll 搜索路径(如果有的话)。

    在不了解您的开发环境的情况下,很难知道如何建议您如何将 list 添加到 dll。如果您正在编辑 .rc 文件并手动输入 list ,请知道在 Dlls 中要使用的资源 ID 是 2,而不是 1,它通常在 exe 示例中使用。

    如果您使用的是 DevStudio 2005 或更高版本,则有一个方便的 #pragma 指令,它可以让所有东西神奇地拥有正确的 ID 并位于正确的位置。

    如果项目设置为默认值,VS2005 及更高版本将自动生成并根据需要嵌入 list 。此#pragma 将添加额外的程序集依赖项
    到生成的 list :-
    #if _MSC_VER >= 1400 // VS2005 added this directive
    #pragma comment(linker, \
    "\"/manifestdependency:type='Win32' "\
    "name='Company.Product.Subsystem' "\
    "version='6.0.0.0' "\
    "processorArchitecture='*' "\
    "language='*'\"")
    #endif

    关于dll - Win32 App插件如何将其DLL加载到自己的目录中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2637499/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com