zoukankan      html  css  js  c++  java
  • 【转】Windows 8 desktop app中dll搜索路径设置的诡异现象,Bug?

    原文地址: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文件来解决,目前还没有尝试。
     
  • 相关阅读:
    03_ if 练习 _ little2big
    uva 11275 3D Triangles
    uva 12296 Pieces and Discs
    uvalive 3218 Find the Border
    uvalive 2797 Monster Trap
    uvalive 4992 Jungle Outpost
    uva 2218 Triathlon
    uvalive 3890 Most Distant Point from the Sea
    uvalive 4728 Squares
    uva 10256 The Great Divide
  • 原文地址:https://www.cnblogs.com/FCoding/p/3312051.html
Copyright © 2011-2022 走看看