首页 > 代码库 > Path环境变量包含不存在的路径时对dll搜索的影响
Path环境变量包含不存在的路径时对dll搜索的影响
在Windows中,根据MSDN的文档,某些情况下应用程序运行时会在Path环境变量指定的目录中搜寻它需要的dll。那么如果Path中包含一个不存在的路径,Windows会如何处理这种情况?我本以为这些路径会被忽略,然后Windows会继续搜索,后来发现其实不然。至少在Windows 7上,cmd和Msys的行为不完全是这样。
假设我有一个应用程序conftest.exe,它依赖于SDL.dll;并且假设SDL.dll放在Path包含的某个目录中。在正常情况下,我在cmd中运行conftest.exe,它会正常运行正常退出,没有任何错误提示。
但是如果我在运行conftest.exe前,通过命令在Path变量的开头添加一个不存在的路径(比如NONE),那么conftest.exe在运行时就会报一个找不到SDL.dll的错误:
> set path="NONE;%path%"
> conftest
(弹框提示找不到SDL.dll。)
但是将NONE放在Path的结尾却不会有这个问题:
> set path="%path%;NONE"
> conftest
(正常运行。)
Msys也是如此;而且在PATH的开头添加NONE之后,就必须通过./conftest这样的形式来启动程序了,即必需指定conftest.exe所在的目录,不能省略./;另外在conftest.exe报错退出后,通过echo $?可发现conftest.exe的返回值为53:
$ export PATH="NONE;$PATH"
$ conftest
sh: conftest: command not found
$ ./conftest
(弹框提示找不到SDL.dll。)
$ echo $?
53
但奇怪的是,如果我通过Windows系统属性对话框中的环境变量设置(方法是右键单击开始菜单中的“计算机”->“属性”->“高级系统设置”->“环境变量”)在Path的开头添加NONE,却不会有这个问题,conftest.exe还是能找到SDL.dll,正常运行。
可见在cmd和Msys中,应用程序在Path中搜索dll时,遇到一个不存在的路径就会停止搜索。
有意思的是,在Msys中,如果在PATH中添加的不存在路径是一个绝对路径,那就不会有问题:
$ export PATH="/NONE;$PATH"
$ conftest
(正常运行。)
$ echo $?
0
$ ./conftest
(正常运行。)
$ echo $?
0
---------------------------------------------------------------------------------------------------------------------------------------
之所以会研究这个问题,是因为最近我用MinGW+Msys构建一个开源项目时,总是遇到找不到dll的错误。经过研究发现是configure运行的时候会生成并运行一些名字叫conftest.exe的可执行文件,用来测试系统上是否安装了某些库或具有某些特性,而conftest.exe可能会依赖于某些dll。但奇怪的是,这些dll就在PATH中,而且如果我根据config.log单独构建出conftest.exe,并且按照config.log中记录的命令单独在终端中(不通过configure)运行它的话,就不会遇到找不到dll的错误。因此我想肯定是configure做了点什么。
果然,后来发现configure在运行conftest.exe之前,会将$prefix/bin和$prefix/usr/bin添加到PATH的开头:
PATH="$prefix/bin:$prefix/usr/bin:$PATH"
而如果用户在运行configure时没有指定--prefix,此时$prefix的值就是NONE,于是这就是两个不存在的目录,影响了dll的搜索。这个链接里也提到了prefix为NONE的事,摘录如下:
Autoconf initialises `prefix=NONE‘, then resets it to what the user gave as the `--prefix=/some/path‘ argument. If the user doesn‘t specify such an argument, then it remains set as `NONE‘ to the end of the configure script, eventually being replaced by `prefix=$ac_default_prefix‘ in config.status, just before generating the AC_CONFIG_FILES; this allows your configure script to check, at any time, whether or not the user specified `--prefix=/some/path‘, (e.g. with `test "$prefix" = NONE‘, although AFAIK this feature is undocumented).
Path环境变量包含不存在的路径时对dll搜索的影响