C++ 确定DLL的加载路径
我希望我的申请采用以下结构C++ 确定DLL的加载路径,c++,windows,visual-studio,dll,C++,Windows,Visual Studio,Dll,我希望我的申请采用以下结构 Exe | |----- DLL\DLL.dll, DLL\common.dll | |----- DLL2\DLL2.dll, DLL2\common.dll 我的EXE将通过加载DLL LoadLibraryEx(_T("DLL\\DLL.dll"), 0, 0); LoadLibraryEx(_T("DLL2\\DLL2.dll"), 0, 0); DLL.DLL和DLL2.DLL项目将通过lib文件链接到common.DLL。不过将有两个不同版本
Exe
|
|----- DLL\DLL.dll, DLL\common.dll
|
|----- DLL2\DLL2.dll, DLL2\common.dll
我的EXE将通过加载DLL
LoadLibraryEx(_T("DLL\\DLL.dll"), 0, 0);
LoadLibraryEx(_T("DLL2\\DLL2.dll"), 0, 0);
DLL.DLL
和DLL2.DLL
项目将通过lib文件链接到common.DLL
。不过将有两个不同版本的common.dll
但是,在执行过程中,
Exe
希望我将common.dll
放在与Exe
相同的目录中,但与dll
和DLL2
不同的目录中。是否有任何方法可以解决这个问题,通过能够有上面的目录结构。但是,仍然使用lib链接DLL/DLL2
和common
好的,这将非常有趣
这里的基本内容是,要从其他路径加载DLL,必须指定完整路径(使用LoadLibrary时)或展开path环境变量以包括包含DLL的其他文件夹。有关如何执行此操作的详细信息,请参见setenv
一个简单的解决方案是提供LoadLibrary的相对路径。但是,您似乎正在链接DLL,因此无法应用此解决方案
问题是无论您的项目布局是什么,运行时链接器都将使用当前工作目录和PATH变量。由于您似乎正在链接库,因此不可能在加载第一个DLL之后和第二个DLL之前“修复”PATH变量。剩下的解决方案是将公共DLL重命名为common-1.DLL和common-2.DLL。这还有一个好处,就是您可以将它们全部放在同一个目录中
(如果您在任何情况下都在使用LoadLibrary,那么只需修复路径变量…)
SetDllDirectory(NULL); // Reset.
SetDllDirectory(""); // Plug "binary planting" security hole. `
SetDllDirectory("C:\MyExePath\DLL");
LoadLibrary("C:\MyExePath\DLL\DLL.dll");
SetDllDirectory(NULL); // Reset.
SetDllDirectory(""); // Plug "binary planting" security hole.
SetDllDirectory("C:\MyExePath\DLL2");
LoadLibrary("C:\MyExePath\DLL2\DLL2.dll");
SetDllDirectory(NULL); // Reset.
SetDllDirectory(""); // Plug "binary planting" security hole.
(未经测试,因此,对于任何错误或遗漏的论点,我深表歉意。不过,我应该告诉你这个想法。)
(您应该在运行时计算C:\MyExePath。显然,硬编码是不好的。)
(我假设DLL.DLL和DLL2.DLL隐式加载它们的common.DLL。如果它们通过LoadLibrary调用加载common.DLL,那么问题就更简单了:只需让它们计算自己的路径,然后将LoadLibrary的完整路径传递给common.DLL。)
注意:SetDllDirectory会影响整个过程。如果您的进程有多个线程,那么您应该确保SetDllDirectory调用以及可能触发LoadLibrary调用的任何其他调用彼此隔离。e、 g.如果可能,在生成任何其他线程之前,在启动时加载库。它不会工作。无法将“DLL2\DLL2.dll”链接到“DLL2\common.dll”。DLL2.dll将与“dll\common.dll”链接。加载“DLL2.dll”时,内存中将有一个“common.dll”,因此DLL2.dll的导入将根据该dll进行解析
请注意,诸如
PATH
或setdldirectory
之类的建议不起作用。它们影响LoadLibrary
查找“common.dll”的方式,但对于dll\dll.dll,LoadLibrary(“common.dll”)
只调用一次 出于安全原因,dotnet1-4仅允许从gac或主路径下方的路径加载库。ie LoadLibraryEx(_T(“..\\DLL.DLL”),0,0;是不允许的。从来没有人说过.Net参与了这件事。而native并不关心+1(尽管我自己的回答是这样的),因为我怀疑您有两个同名的DLL是正确的,如果它们是这样加载的。(不过,我回答的主要部分对问题的另一半仍然有用。)你是对的。如果正在加载DLL\common.DLL,则不会加载DLL2\common.DLL。您认为有什么方法可以解决这个问题吗?您可以将DLL更改为使用LoadLibrary(非隐式链接)并指定其各自DLL的完整路径吗?即使您不能重命名DLL,也应该可以使用。例如,在Explorer中加载了许多具有相同(选择不当、通用)名称的shell扩展DLL。(除非这些东西不起作用?)我刚才提到的例子:@Leo Davidson:shell扩展DLL是COM组件;显然,Explorer.EXE没有针对它们进行链接。该限制实际上是在导入部分,而不是在LoadLibrary
中。是的。你的解决方案很有效。这使我能够从不同的目录加载DLL。只是,加载同名DLL时会出现问题。请问,哪里有“插件”二进制植入“安全漏洞”?@Yan See here:--有关更多信息,请参阅here:@LeoDavidson我想加载同名同一DLL的两个版本。这只是为了测试的目的,以确保结果在某种程度上不同,我希望他们有所不同。在这一点上,重命名将是太多的工作,所以有办法做到这一点吗?