更改静态链接DLL的DLLsearchpath

我已经search了任何提示,我可以做到这一点,但我发现的是如何将SxS DLLredirect到本地应用程序文件夹。 这是我想要完成的:(C ++)Application.exe链接到一个DLL,Plugin.DLL(依赖项目)。 这个DLL不是放在应用程序目录中,而是放在一个名为“插件”的子文件夹中。 由于DLL是静态链接的,应用程序会尝试从应用程序文件夹加载它。

有没有办法如何改变这个特定的DLL的searchpath? 通过清单或VS2008链接器configuration?

我的第一个想法是,如果你是静态链接一个DLL,它不是一个插件。 只需将该DLL在EXE文件夹中,并完成它。 这是由静态加载的DLL支持的Windows部署configuration。

也就是说,有办法实现你想要的。 但他们大多是愚蠢的,或者没有理由的复杂:你的select是:

  • 不要静态链接。 使用LoadLibrary(“plugins / Plugin.dll”)和GetProcAddress来访问插件内容。
  • 将“到您的插件文件夹的path”添加到系统PATH环境variables。
  • 使用延迟加载机制来延迟访问插件function,设置一个自定义帮助函数 ,可以使用提供的path加载DLL。
  • 将plugins文件夹转换成一个程序集(通过在其中创build一个列出plugin.dll的.manifest文件)。 将“插件”作为附属程序集添加到您的应用程序中。 现在它将在插件文件夹中查找。
  • 将您的应用程序分成一个stub exe和一个dynamic加载的部分。 在stub exe中调用SetDllDirectory指向插件文件夹,然后调用LoadLibrary将完整path传递给“appstub.dll”。

要将一个或多个dll文件夹转换为“程序集”,只需将文件添加到文件夹name.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开始查看其embedded式清单文件有关该程序集的信息。

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

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

扩充和详述克里斯关于 “大会”子目录的build议:


附注:克里斯还有两个优秀的写作更多的细节:

  • 使用清单 回答 DLLredirect
  • 答案 从中央资源库加载DLL的方法

    这也解释了如何在应用程序configuration文件中利用probing privatePath来将DLL放在子文件夹之外。


MS文档

这实际上被称为“私人大会” ,MS文件这样解释:

专用程序集安装在应用程序目录结构的文件夹中。 通常,这是包含应用程序的可执行文件的文件夹。 专用程序集可以部署在与应用程序相同的文件夹中,与程序集名称相同的文件夹中, 也可以与程序集名称相同的语言特定的子文件夹中进行部署

例如 (…)

Appdir\Microsoft.Tools.Pop\Microsoft.Tools.Pop.MANIFEST :清单部署为具有程序集名称的子文件夹中的单独文件。

(……)

专用程序集可以通过任何可以将程序集文件复制到此文件夹的安装方法来安装,例如xcopy命令。

这个例子

你在程序文件夹C:\Test\Program\app.exe得到了可信的旧可执行文件,并且希望在加载时 – 从Plugins子文件夹加载DLL文件,即C:\Test\Program\plugins\tool1.dll 而不会PATH或其他任何东西混淆。

你需要:

  • 编译app.exe:

     #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 

    注意:在我的testing系统中需要编译/链接它,而不是使用外部清单( app.exe.manifest ),我还没有find原因。 (*一个)

    但是,也可以使用mt工具将下面列出的清单文件embedded/合并到可执行文件中,而不是使用链接器编译指示符。 ( Configuration > Manifest Tool > Additional Manifest Files

  • 把tool1.dll介绍plugins子文件夹

  • 添加一个plugins.manifest文件插件子文件夹,即C:\Test\Program\plugins\plugins.manifest ,看起来像这样:

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> 

而已。 启动app.exe将自动在Load-Time的子文件夹中finddll。


(* a):合并这个清单文件是可行的,但是你不能把它作为唯一的外部清单文件,我怀疑这是因为它缺less了构build系统已经放到你的可执行文件中的所有其他清单信息。

 <?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>