原文地址:http://blog.csdn.net/my_business/article/details/8850151

某个桌面程序在win 8上运行异常的问题困扰了我有近一周,今天终于找到了根本原因,严重怀疑是win 8的一个Bug。
(所有程序都是desktop app,跟Metro模式无关)
情况是这样的,比如有个Main.exe会通过CreateProcess启动另外一个Sub.exe,而这个Sub.exe中会通过LoadLibrary动态加载多个动态链接库,Main.exe和Sub.exe以及相关dll都不在同一路径,所以在Sub.exe中会通过SetCurrentDirectory来设置dll的搜索路径以保证LoadLibrary可以正常找到dll并加载。这些程序在WinXP,Win7下都运行正常,但是到了Win8下运行时就报出某dll找不到(126)的错误。比较了代码以及一切相关设置都跟Win7完全相同,但dll就是不能正常加载。
 
第一层分析,检查了在Win8下SetCurrentDirectory是否正常工作,发现设置成功,一切正常。然后查了MSDN,windows下dll默认的搜索路径是:
1. 应用程序所在的路径
2. 当前目录(SetCurrentDirectory所设置的路径)
3. Windows SYSTEM目录。通过调用GetSystemDirectory函数可以获取这个目录的路径。
4. 16位系统的目录。并没有函数可以获取这个目录的路径,但是它会被查找。
5. Windows目录。通过调用GetWindowsDirectory函数可以获取这个目录的路径。
6. PATH环境变量指定的路径。
也就是说通过SetCurrentDirectory设置的第二项“当前目录”,在dll检索中没有起作用。那什么API会影响到dll搜索路径呢?
 
第二层分析,发现通过SetDllDirectory这个API可以直接设置dll搜索路径,而通过此API设置后搜索路径就变成:
1. 应用程序所在的路径
2. SetDllDirectory所设置的路径
3. Windows SYSTEM目录。通过调用GetSystemDirectory函数可以获取这个目录的路径。
4. 16位系统的目录。并没有函数可以获取这个目录的路径,但是它会被查找。
5. Windows目录。通过调用GetWindowsDirectory函数可以获取这个目录的路径。
6. PATH环境变量指定的路径。
也就是说如果你使用过SetDllDirectory来设置路径,那即使你再用SetCurrentDirectory来设置当前路径,它也不会属于dll搜索路径中。
 
第三层分析,难道是Sub.exe或者某个dll中调用了SetDllDirectory,搜索了下,一个没有。总不会是Main.exe中有调用从而会影响到Sub.exe吧?搜了下Main.exe的相关代码,确实发现有几处调用了SetDllDirectory。尝试在Sub.exe中通过GetDllDirectory打出该路径,发现不为空,确实是在Main.exe设置过的值。基本确定是原因。
 
第四层分析,那SetDllDirectory的设置怎么会从Main.exe传递到了Sub.exe,查看了调用CreateProcess的第五个参数(关于句柄继承的那项),确实设置成True了,难道这个改下就能解决?立马改成False,再试,还是失败。何况一样的处理在Win7下是正常的,说明肯定有什么特性在Win8下有差异。再回到SetDllDirectory,在Win7下尝试了下,不管CreateProcess的第五个参数设置True还是False,Main.exe中SetDllDirectory的设置都不会传递到Sub.exe,而Win8则相反会传递。
 
第五层分析,那怎么解决呢?尝试了在Main.exe调用CreateProcess启动Sub.exe前,或者在Sub.exe中通过SetDllDirectory(“”)来清除已有的设置,可以解决这个问题。另外比较推荐在所有通过调用SetDllDirectory来设置搜索路径并加载关联dll后马上通过SetDllDirectory(“”)来清除,防止影响到后续的其他处理。
 
目前为止仍旧想不通为什么会有这么恶心的区别。
 
结论:
  1. 这很可能是属于 Win8的一个 Bug
  2. 由于 Win7和 Win8下的这些差异,尽量保证 exe和所关联 dll在同一路径,或者尽量都用绝对路径去调用 LoadLibrary
  3. 如果使用 SetCurrentDirectory来配置 dll搜索路径时,当 exe由其他进程启动时,系统变量或句柄会可能受父进程的影响
  4. 网上还看到可以通过manifest文件来解决,目前还没有尝试。
 

【转】Windows 8 desktop app中dll搜索路径设置的诡异现象,Bug?的更多相关文章

  1. DLL搜索路径和DLL劫持

    DLL搜索路径和DLL劫持 环境:XP SP3 VS2005 作者:magictong 为什么要把DLL搜索路径(DLL ORDER)和DLL劫持(DLL Hajack)拿到一起讲呢?呵呵,其实没啥深 ...

  2. 关于DLL搜索路径顺序的一个问题

    DLL的动态链接有两种方法.一种是加载时动态链接(Load_time dynamic linking).Windows搜索要装入的DLL时,按以下顺序:应用程序所在目录→当前目录→Windows SY ...

  3. 关于指定dll搜索路径

    原文:关于指定dll搜索路径 问题现象 当部分DLL放在子文件夹下,需要指定DLL搜索路径,否则系统将找不到文件 产生原因 系统默认搜索只会在前程序目录并不包括子目录 解决方法 1,使用App.con ...

  4. 关于DLL搜索路径的顺序问题

    DLL的动态链接有两种方法.一种是加载时动态链接(Load_time dynamic linking).Windows搜索要装入的DLL时,按以下顺序:应用程序所在目录→当前目录→Windows SY ...

  5. C和C++中include 搜索路径的一般形式以及gcc搜索头文件的路径

    C和C++中include 搜索路径的一般形式 对于include 搜索的路径: C中可以通过 #include <stdio.h> 和 #include "stidio.h&q ...

  6. .NET 6学习笔记(4)——如何在.NET 6的Desktop App中使用Windows Runtime API

    Windows Runtime API是当初某软为了区别Win32 API,力挺UWP而创建的另一套Windows 10专用的API集合.后来因为一些原因,UWP没火.为了不埋没很有价值的Window ...

  7. Linux 静态库与动态库搜索路径设置详解【转】

    原文地址:http://blog.chinaunix.net/uid-29025972-id-3855495.html 1. 连接和运行时库文件搜索路径的设置 库文件在连接(静态库和共享库)和运行(仅 ...

  8. linux动态库默认搜索路径设置的三种方法

    众所周知, Linux 动态库的默认搜索路径是 /lib 和 /usr/lib .动态库被创建后,一般都复制到这两个目录中.当程序执行时需要某动态库, 并且该动态库还未加载到内存中,则系统会自动到这两 ...

  9. LaTeX自定义宏包、类文件的默认搜索路径设置方法

      对于自定义的LaTeX宏包与类,在调用时可以通过在命令\documentclass{}与\usepackage{}命令中指定完整路径或者相对路径,这样确实可以调用,但是编译时总是有烦人的警告信息, ...

随机推荐

  1. ng-repeat动态改变样式

    当我们使用AngularJs的ng-repeat时候动态绑定数据时,遇到遍历出来的标签样式都一样,这时候希望根据数组的下标分别对应不同的样式 解决:使用$index获取数组下标根据下标改变样式 < ...

  2. 动态创建控件 #Create(...)

    在类中创建一个控件对象;例:CButton m_btn; 用Create创建一个对象(#其实已经与其绑定)m_btn.Create(.....); #注意Create()函数的参数 问题一:点击一个b ...

  3. mysql高级

    视图: 视图是一条select语句执行后返回的结果集 试图是对若干张基础表的引用 定义视图: 建议以v_开头 create view 试图名称 as select 语句 查看视图 show table ...

  4. 可以替代alert 的漂亮的Js弹框

    1 基本弹框 2确认框 3又一种确认框 4带返回的弹框 5带返回的探矿 6 6 一切尽在 http://t4t5.github.io/sweetalert/

  5. java基础-day18

    第07天 集合 今日内容介绍 u  HashSet集合 u  HashMap集合 第1章   HashSet集合 1.1  Set接口的特点 Set体系的集合: A:存入集合的顺序和取出集合的顺序不一 ...

  6. csdn上讲一个实时计算架构比较清晰的一篇文章

    https://blog.csdn.net/ymh198816/article/details/51998085

  7. bootstrap手风琴折叠

    <!DOCTYPE html><html> <head> <meta charset="utf-8" /> <title> ...

  8. OmniThreadLibrary学习笔记

    http://blog.sina.com.cn/s/articlelist_1157240623_6_1.html 非常好的控件,仔细看

  9. MySQL--Percona-XtraDB-Cluster使用xtrabackup来添加节点

    虽然PXC支持在线增加群集节点,但是目前尚未解决wsrep_sst_method=xtrabackup 或wsrep_sst_method=mysqldump时报错的问题,因此尝试手动完成xtraba ...

  10. Python学习--和 Oracle 交互(2)

    当在 mac 电脑上用 Python 读取 oracle 数据库中的中文时,有可能返回数据为“?” 解决方案: 在数据库操作的函数前添加以下代码, import sysreload(sys)sys.s ...