更改静态链接 DLL 的 DLL 搜索路径

2021-12-18 00:00:00 dll redirect linker c++ manifest

我已经搜索了如何执行此操作的任何提示,但我发现的只是如何将 SxS DLL 重定向到本地应用程序文件夹.这是我想要完成的:(C++) Application.exe 链接到一个 DLL Plugin.DLL(依赖项目).这个 DLL 不放在应用程序目录中,而是放在一个名为插件"的子文件夹中.由于 DLL 是静态链接的,应用程序将尝试从应用程序文件夹加载它.

I've searched for any hints how I can do this, but all I found was how to redirect a SxS DLL to the local application folder. Here is what I want to accomplish: The (C++) Application.exe is linked to a DLL, Plugin.DLL (dependant project). This DLL is not placed inside the application directory, but in a subfolder called "plugins". As the DLL is statically linked, the application would try to load it from the application folder.

有什么方法可以更改此特定 DLL 的搜索路径?是通过清单还是 VS2008 链接器配置?

Is there any way how I can change the search path for this particular DLL? Either through manifests or VS2008 linker configurations?

推荐答案

我的第一个想法是,如果您静态链接一个 dll,它就不是一个插件.只需将 dll 放在 EXE 文件夹中即可完成.那就是 windows 支持的静态加载 DLL 的部署配置.

My first thought is, if you are statically linking a dll, it isnt a plugin. Just put the dll in the EXE folder and be done with it. That is the deployment configuration supported by windows for statically loaded DLLs.

也就是说,有很多方法可以实现您想要的.但它们大多是愚蠢的,或者无缘无故地复杂:您的选择是:

That said, there are ways to achieve what you want. But they are mostly stupid, or complicated for no good reason: Your options are:

  • 不要静态链接.使用 LoadLibrary("plugins/Plugin.dll") &GetProcAddress 以访问插件内容.
  • 将插件文件夹的路径"添加到系统 PATH 环境变量中.
  • 使用延迟加载机制延迟访问插件功能,设置自定义帮助程序 可以使用提供的路径加载 dll 的函数.
  • 将插件文件夹转换为程序集(通过在其中创建一个列出 plugin.dll 的 .manifest 文件).将插件"作为依赖程序集添加到您的应用程序.现在它将在插件文件夹中查找.
  • 将您的应用程序拆分为存根 exe 和动态加载的部分.在存根 exe 中调用 SetDllDirectory 指向插件文件夹,然后调用 LoadLibrary 将完整路径传递给appstub.dll".
  • Don't statically link. Use LoadLibrary("plugins/Plugin.dll") & GetProcAddress to access plugin content.
  • Add "the path to your plugins folder" to the systems PATH environment variable.
  • Use the delay load mechanism to delay accessing the plugins functionality, set a custom helper function that can load the dll(s) using a provided path.
  • Turn the plugins folder into an assembly (by creating a .manifest file in it that lists the plugin.dll). Add "plugins" as a dependent assembly to your app. Now it will look in the plugins folder.
  • Split your application into a stub exe and a dynamically loaded part. In the stub exe call SetDllDirectory to point to the plugin folder, then call LoadLibrary passing the full path to "appstub.dll".

要将带有一个或多个 dll 的文件夹转换为程序集",只需将一个文件添加到文件夹名称为.manifest 的文件夹即可.

To turn a folder, with one or more dll's into an "assembly", simply add a file to the folder with the folders name.manifest.

所以,plugins.manifest :-

So, plugins.manifest :-

<assembly manifestVersion="1.0">
  <assemblyIdentity type="Win32" name="Plugins" version="1.0.0.0" processorArchitecture="x86" />
  <file name="Plugin.dll"/>
</assembly>

确保文件夹和 dll 的名称不同是一个非常好的主意,就像 dll 名称是程序集名称一样,Windows 开始查看其嵌入的清单文件以获取有关程序集的信息.

It is a VERY good idea to ensure that the folder and the dll's name is different as if the dll name is the assembly name windows starts looking at its embedded manifest file for information about the assembly.

假设您使用的是 Visual Studio 7 或更高版本,添加到项目中的 .c/.cpp 或 .h 文件的以下指令将使您的应用程序尝试从程序集加载 dll,而不仅仅是本地目录:

Assuming you are using Visual Studio 7 or later, the following directive added to a .c/.cpp or .h file in the project will then make your application attempt to load dlls from the assembly rather than just the local directory:

#pragma comment(linker, "/manifestdependency:"name='Plugins' "
                        "processorArchitecture='*' version='1.0.0.0' "
                        "type='win32'"")

相关文章