在项目从VS2010升级到VS2015过程中,遇到了一些dll的依赖问题,升级程序在appdata目录中,希望引用安装目录中的运行时库以及libcurl等功能依赖组件。复习了一下这块的资料作一下总结:
首先是SafeDllSearchMode的概念,是否开启的标志位于HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\SafeDllSearchMode
自windowsXP SP2开始默认开启
If SafeDllSearchMode is enabled, the search order is as follows:
- The directory from which the application loaded.(程序目录)
- The system directory. Use the GetSystemDirectory function to get the path of this directory.(system目录)
- The 16-bit system directory. There is no function that obtains the path of this directory, but it is searched.
- The Windows directory. Use the GetWindowsDirectory function to get the path of this directory.(windows目录)
- The current directory. (当前工作目录)
- The directories that are listed in the PATH environment variable. Note that this does not include the per-application path specified by theApp Paths registry key. The App Paths key is not used when computing the DLL search path.(环境变量PATH目录)
If SafeDllSearchMode is disabled, the search order is as follows:
- The directory from which the application loaded.(程序目录)
- The current directory. (当前工作目录)
- The system directory. Use the GetSystemDirectory function to get the path of this directory. (system目录)
- The 16-bit system directory. There is no function that obtains the path of this directory, but it is searched.
- The Windows directory. Use the GetWindowsDirectory function to get the path of this directory.(windows目录)
- The directories that are listed in the PATH environment variable. Note that this does not include the per-application path specified by theApp Paths registry key. The App Paths key is not used when computing the DLL search path.(环境变量PATH目录)
差别在于搜索程序所在目录后的第二选择是 系统目录,还是当前的工作目录。
SetDllDirectory可以添加一个指定目录到搜索顺序中,并且作为仅次于程序所在目录的优化级,但是需要注意的是,这种方式仅能够针对LoadLibrary和LoadLibraryEx
在工程中隐式包含加载时,由于隐式加载的DLL是在EXE主体模块之前加载进来的,执行顺序上是先通过PE文件的导入表加载隐式的DLL,因此无法更改隐式加载的dll搜索顺序。
此外,
manifest文件也可以控制dll的加载文件。
需要注意的是,
1.在开始搜索dll前,如果内存中已经有了同名的dll,那么系统会使用已经加载过的dll文件,而不会考虑这个dll文件位于什么目录中
2.如果dll是knows dlls,如user32.dll,那么系统使用该dll的拷贝,而不会去搜索。knows dll位于HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\KnownDLLs中
- If a DLL with the same module name is already loaded in memory, the system uses the loaded DLL, no matter which directory it is in. The system does not search for the DLL.
- If the DLL is on the list of known DLLs for the version of Windows on which the application is running, the system uses its copy of the known DLL (and the known DLL's dependent DLLs, if any). The system does not search for the DLL. For a list of known DLLs on the current system, see the following registry key: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\KnownDLLs.
参考:https://msdn.microsoft.com/en-us/library/ms682586(v=vs.85).aspx