原文地址: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. 20155205 2016-2017-2 《Java程序设计》第3周学习总结

    20155205 2016-2017-2 <Java程序设计>第3周学习总结 教材学习内容总结 第四章 定义类的两种方法(new和this的用法) 只要有一个类定义,编译程序就会产生一个. ...

  2. Python 之 Difflib

    Python 之 Difflib 2017年7月8日 word文档地址:https://wenku.baidu.com/view/36692440854769eae009581b6bd97f19237 ...

  3. reload maven project' has encountered a proble" 问题

    由于重重原因,我取消maven的下载(可能是jar包没有公服镜像).导致重新打开sts 时发生异常. 在网上寻找到资料,发现需要删除${workspace}\.metadata\.plugins\or ...

  4. Jmeter-接口功能测试

    前言 前面已经讲过了如何用Postman做接口功能测试,本篇主要是用Jmeter来演示如何做接口功能测试,这里就大致说一下Jmeter如何用哈,其余的也不多说了. Jmeter接口功能测试实例 因为在 ...

  5. eclipse查看方法被那些代码调用open call hierarchy

    当我们编写的代码量十分巨大,项目十分复杂的时候,想要查找某一个方法都被其他那些代码调用了是一件十分困难的事,然后Eclipse提供了十分方便的方法用于查看方法都被那些代码调用了. 方法一: 选中要查看 ...

  6. 关于FPGA的一些小见解

    Xilinx FPGA配置bit流文件 Xilinx FPGA的供电是采用USB作为电源,使用Verilog HDL或VHDL实现的逻辑电路通过Xilinx的综合工具生成bit流文件,通过Digile ...

  7. myeclipse6.6+maven跑springside4.1的demo

    1.安装myeclipse6.6 2.myeclipse6.6安装maven 2.1 删除原有maven. 关闭Eclipse程序, 进入MyEclipse插件目录/eclipse/features ...

  8. JS学习笔记3_函数表达式

    1.函数表达式与函数声明的区别 函数声明有“提升”(hoisting)的特性,而函数表达式没有.也就是说,函数声明会在加载代码时被预先加载到context中,而函数表达式只有在执行表达式语句时才会被加 ...

  9. ionic 2.x 3.x项目结构解析

    myApp │ config.xml //项目配置文件,包名.名称.minSdkVersion等都在此处配置 │ ionic.config.json │ package.json //项目依赖文件列表 ...

  10. 【转】JS浮点数运算Bug的解决办法

    37.5*5.5=206.08 (JS算出来是这样的一个结果,我四舍五入取两位小数) 我先怀疑是四舍五入的问题,就直接用JS算了一个结果为:206.08499999999998 怎么会这样,两个只有一 ...