原文地址: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. jquery取消事件冒泡的三种方法展示

    jquery取消事件冒泡的三种方法展示 html代码 <!doctype html> <html> <head> <meta charset="ut ...

  2. 1033 To Fill or Not to Fill

    PAT A 1033 To Fill or Not to Fill With highways available, driving a car from Hangzhou to any other ...

  3. Ng第十一课:机器学习系统的设计(Machine Learning System Design)

    11.1  首先要做什么 11.2  误差分析 11.3  类偏斜的误差度量 11.4  查全率和查准率之间的权衡 11.5  机器学习的数据 11.1  首先要做什么 在接下来的视频将谈到机器学习系 ...

  4. 最完美的Linux桌面软件

    下面是关于Linux桌面环境下,目前为止最完美的部分.之所以说他们完美,是因为他们不但很养眼,而且也使用最好的多媒体技术,有最好的可用性.在某些方面,他们甚至超过了Windows和Mac-OS. 基础 ...

  5. 20145232 《Java程序设计》课程总结

    学期总结 实验报告链接汇总 实验一 Java开发环境的熟悉 实验二 Java面向对象程序设计 实验三 敏捷开发与XP实践 实验四 Andoid开发基础 实验五 Java网络编程 代码托管链接 :Jav ...

  6. 20145232 韩文浩 《Java程序设计》第3周学习总结

    教材学习内容总结 在第三章中,知道了Java可区分为基本类型和类类型两大类型系统,其中类类型也称为参考类型.在这一周主要学习了类类型. 对象(Object):存在的具体实体,具有明确的状态和行为 类( ...

  7. 【python3+request】python3+requests接口自动化测试框架实例详解教程

    转自:https://my.oschina.net/u/3041656/blog/820023 [python3+request]python3+requests接口自动化测试框架实例详解教程 前段时 ...

  8. Android x86模拟器Intel Atom x86 System Image配置与使用方法

    Android x86模拟器Intel Atom x86 System Image配置与使用方法      前言:      大家现在开发使用的Android 模拟器模拟的是 ARM 的体系结构(ar ...

  9. datetime & time

    python有两个和时间相关的模块,datetime和time datetime datetime模块下有四个类 date     日期相关的 time          时间相关的 datetime ...

  10. [转载]持续交付和DevOps的前世今生

    作者/分享人:乔梁,20年IT老兵,腾讯公司高级管理顾问,敏捷和精益开发专家,持续交付领域先行者.曾就职于百度,国内多个知名互联网公司的企业教练. 历年QCon技术大会的讲师和专题出品人. 这是一个新 ...