Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/windows/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/csharp-4.0/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 确定DLL的加载路径_C++_Windows_Visual Studio_Dll - Fatal编程技术网

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,那么只需修复路径变量…)

  • 您希望将两个具有相同名称(common.dll)的不同dll加载到同一进程中。

    这对我来说似乎是个坏主意。真的有必要吗?其中一个可以重新命名吗

  • 确保加载的DLL可以找到不在搜索路径中的其他DLL。

    (如果您没有动态加载DLL.DLL和DLL2.DLL,那么我不确定会是什么。幸运的是,我看到您是:)

    如果要动态加载DLL.DLL和DLL2.DLL(即在运行时使用LoadLibrary,而不是在生成时链接到它们的.lib文件),则可以事先调用,将DLL或DLL2目录显式添加到搜索路径。您希望一次只在路径中有一个目录,以确保加载了正确的common.dll

    请注意,最好在程序开始时调用SetDllDirectory(“”),以从DLL搜索路径中删除当前工作目录(不要担心,不是程序的目录),除非它破坏了编写不好的组件。这缓解了代码可能被诱骗加载DLL的安全问题。但是还要注意,如果通过调用SetDllDirectory(NULL)重置搜索路径,那么之后需要再次调用SetDllDirectory(“”)

  • 所以你会有这样的代码:

    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的两个版本。这只是为了测试的目的,以确保结果在某种程度上不同,我希望他们有所不同。在这一点上,重命名将是太多的工作,所以有办法做到这一点吗?