我已经搜索了任何线索以确定如何完成此操作,但我找到的只是如何将SxS DLL重定向到本地应用程序文件夹的方法。以下是我想要实现的内容:
(C++) Application.exe链接到一个名为 Plugin.DLL(依赖项目)的DLL文件,但该DLL文件不位于应用程序目录中,而是位于名为“plugins”的子文件夹中。由于该DLL被静态链接,应用程序会尝试从应用程序文件夹中加载它。
是否有任何方式可以更改特定DLL文件的搜索路径?可以通过清单或VS2008链接器配置来实现吗?
我的第一反应是,如果你在静态链接一个dll,它不是一个插件。只需将dll放入EXE文件夹中即可完成部署配置,这是Windows支持静态加载DLL的方式。
话虽如此,还有一些方法可以实现你想要的功能。但它们大多数都很愚蠢,或者没有必要变得复杂:你的选择有:
要将一个包含一个或多个dll的文件夹转换为"程序集",只需向该文件夹添加一个名为文件夹名称.manifest的文件即可。
因此,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会查看其嵌入式清单文件以获取有关程序集的信息。
假设您正在使用Visual Studio 7或更高版本,则在项目中添加以下指令到.c/.cpp或.h文件中,然后您的应用程序将尝试从程序集加载dll,而不仅仅是从本地目录加载:
#pragma comment(linker, "/manifestdependency:\"name='Plugins' "\
"processorArchitecture='*' version='1.0.0.0' "\
"type='win32'\"")
扩展和详细阐述Chris的提议,“装配”子目录:
附注:Chris还有两篇更详细的文章:
这篇文章还解释了如何利用应用程序配置文件中的探测私有路径
将DLL放在子文件夹之外。
实际上,这被称为"私有程序集",MS文档这样解释:
私有程序集安装在应用程序的文件夹结构中。通常,这是包含应用程序可执行文件的文件夹。私有程序集可以部署在与应用程序相同的文件夹中,在具有相同名称的程序集的文件夹中或在具有相同名称的语言特定子文件夹中。
例如(...)
Appdir\Microsoft.Tools.Pop\Microsoft.Tools.Pop.MANIFEST
:清单作为一个单独的文件部署在一个名为程序集的子文件夹中。(...)
任何可以将程序集文件复制到此文件夹中的安装方法都可以安装私有程序集,如
xcopy
命令。
C:\Test\Program\app.exe
,你想要在 加载时 从 Plugins
子文件夹中加载你的 DLL 文件,即 C:\Test\Program\plugins\tool1.dll
,不需要 操纵 PATH
或其他任何东西。
你需要:
Compile app.exe with:
#pragma comment(linker, "/manifestdependency:\"name='Plugins' version='1.0.0.0' type='win32'\"")
// name, type and version seems to be the minimum info to get away with
Note: Compiling/Linking this in, instead of using an external manifest (app.exe.manifest
) is required on my test system, I didn't find out why yet. (*a)
What also works however is embedding/merging the manifest file listed below into the executable with the mt
tool, instead of with the linker pragma. (Configuration > Manifest Tool > Additional Manifest Files
)
put tool1.dll intro the plugins
subfolder
C:\Test\Program\plugins\plugins.manifest
and that one looks like this:plugins.manifest:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity
type="win32"
name="Plugins"
version="1.0.0.0"
/>
<file name="tool1.dll"/>
</assembly>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<dependency>
<dependentAssembly>
<!-- Note: type: The value must be win32 and all in lower case. Required. -->
<!-- Note: version: The value must be win32 and all in lower case. Required. -->
<assemblyIdentity
type="win32"
name="plugins"
version="1.0.0.0"
/>
</dependentAssembly>
</dependency>
</assembly>
SetDllDirectory
函数;可以使用__pfnDliNotifyHook2
钩子,直接调用LoadLibrary(".\\plugins\\PluginX.dll")
。使用%PATH%
变量的想法有些脆弱,因为它在检查位置列表中排名较低。 - MSalters