为什么当前目录会改变

8

调用 GetOpenFileName 后,进程的当前目录会更改为由 GetOpenFileName 打开的文件所在的目录。


如何保留默认的当前目录?


2
通过保存并恢复它,一旦调用返回。虽然这回答了你的问题,但你真正应该做的是完全不依赖当前工作目录。你刚刚经历了其中一个原因。 - IInspectable
1
那么,继续创建您需要的所有文件。但是,为什么您坚持认为这需要依赖于当前工作目录呢? - IInspectable
1
今天节省的15分钟,可能会在未来几天、几周甚至几个月内花费更多时间来支持你故意实现的错误。而什么样的“可移植性”依赖于一个不变量,而这个不变量却并非如此呢? - IInspectable
1
这是每个搜索引擎都可以为您找到的东西。 - David Heffernan
并非如此。许多东西可以通过搜索轻松找到,但也有很多东西非常难以搜索。在这种情况下,IFileDialog显然属于前一类。顺便说一句,您观察到的行为是有充分文献记录的,因此这个问题也属于前一类。 - David Heffernan
显示剩余11条评论
2个回答

12
我该如何保留默认的当前目录呢?如果您阅读OPENFILENAME文档,就会发现有一个OFN_NOCHANGEDIR标志,用于这个确切的目的:恢复当前目录为其原始值,如果用户在搜索文件时更改了目录。尽管文档声称这个标志在GetOpenFileName()中得到支持。此外,还可以参考雷蒙德·陈(Raymond Chen)关于这个主题的博客文章:为什么通用文件对话框会改变当前目录?

1
哦,文档上说标志会将当前目录恢复到其原始值,但 Raymond 的文章说它会阻止当前目录被更改;你知道实际上会发生什么吗?(当然,对于单线程程序来说这并不重要。) - Harry Johnston
我阅读文章,不会复制粘贴示例代码。我忽略了它,因为它说这样做不会有任何影响。我应该记住winapi文档是一个糟糕的文档示例。 - Imobilis
3
OFN_NOCHANGEDIR选项在对话框关闭时恢复原始工作目录。用户在对话框内浏览文件系统时,仍然可以更改工作目录。 - Remy Lebeau
1
好的,谢谢。这意味着只有 GUI 线程使用当前目录时,此解决方案才能正常工作,我猜如果在处理计时器消息时打开文件,你也可能会自欺欺人。(对于 OP 来说可能没问题,但我提到它是为了未来读者的利益。) - Harry Johnston
3
工作目录是进程全局的,可以影响多个线程。Raymond的博客文章中有一条关于此的评论:"当您指定OFN_NOCHANGEDIR时,GetOpenFileName仍会在运行时更改当前目录。唯一的区别是,在函数退出时,此标志将恢复先前的当前目录。这意味着在多线程应用程序中,您必须小心,在GetOpenFileName正在运行时���要在其他线程中使用相对路径。" - Remy Lebeau
根据 Raymond Chen 文章中的 这条评论OFN_NOCHANGEDIR 标志在 Win Vista 中已经支持 GetOpenFileName - GetFree

4

当前目录之所以存在,是因为对于命令行工具非常方便。对于 GUI 应用程序而言,它通常没有太多用处,这可能就是微软开发人员没有考虑让 GetOpenFileName() 更改它的原因。当然也有偶尔会使用到它的边缘情况,但是从你的问题中很难确定是否属于该情况。(你确定你需要的是当前目录,而不是包含可执行文件的目录吗?)

无论如何,如果你确实需要当前目录,最安全的方法是在程序启动时检索它,并使用保存的值构造完全合格的路径。不要仅仅在你认为可能已经更改了当前目录时恢复原始的当前目录,而是自己构建完全合格的路径。这在多线程代码或未来可能需要成为多线程的代码中尤其重要(即几乎所有情况),这也消除了忽略一个或多个可能更改当前目录的代码路径的风险。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接