警惕使用System.Environment.CurrentDirectory遇到的坑

今天调试程序的时候遇到一个大坑,程序A(exe)通过Process Start启动程序B(exe)进程,总是报错。

from clipboard

上图是程序结构,为了让所有的程序B实例共享配置,所以把app.ini放在了bin的上级目录。

启动进程代码:

 

  1. System.Diagnostics.Process p = new System.Diagnostics.Process();
  2. p.StartInfo = new ProcessStartInfo(fileName);
  3. p.Start();

最后定位到配置文件路径读取问题。这是System.Environment.CurrentDirectory遇到大坑。

 

程序B中有一下代码是用于获取app.ini中的配置:

 

  1. DirectoryInfo topDir = Directory.GetParent(System.Environment.CurrentDirectory);
  2. string iniFileName = Path.Combine(topDir.FullName, "app.ini");

问题症状:

通过程序A启动B,报错。但是通过单独启动程序B正常。

后来发现System.Environment.CurrentDirectory确实是获取当前目录没错,但是如果A程序调用B程序,当B程序里使用了System.Environment.CurrentDirectory获取目录。那么这个B程序里获取的这个目录就不再是B的应用程序所在目录了;而变成了A所在的目录了。

 

解决方案:

1、使用Application.StartupPath获取目录,需要引用:using System.Windows.Forms,因此这个方法只能用于winform程序。

2、使用AppDomain.CurrentDomain.BaseDirectory,通用方案,可以用于类库。

 

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++

后来发现很多网友和我遇到过一样的问题。

下面引用一下网友写的文章:

https://blog.csdn.net/albert528108/article/details/102958457

  1. // 获取程序的基目录。
  2. System.AppDomain.CurrentDomain.BaseDirectory
  3. // 获取模块的完整路径。
  4. System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName
  5. // 获取和设置当前目录(该进程从中启动的目录)的完全限定目录。
  6. System.Environment.CurrentDirectory
  7. // 获取应用程序的当前工作目录。
  8. System.IO.Directory.GetCurrentDirectory()
  9. // 获取和设置包括该应用程序的目录的名称。
  10. System.AppDomain.CurrentDomain.SetupInformation.ApplicationBase
  11. // 获取启动了应用程序的可执行文件的路径。
  12. System.Windows.Forms.Application.StartupPath
  13. // 获取启动了应用程序的可执行文件的路径及文件名
  14. System.Windows.Forms.Application.ExecutablePath

我以前写的代码中获取当前路径基本上都是使用的System.Environment.CurrentDirectory。

但是最近在用另外一个程序A去调用以前的程序B的时候就出现问题了,程序A的作用只是单纯调取程序B的exe文件,在B执行过程中总是真到当前路径这块就出现了问题,实际找到的路径是程序A的路径。

    程序A目录:D:\a
    程序B目录:D:\b
    当程序A调用程序B时,程序B中的Environment.CurrentDirectory结果是D:\a,而不是D:\b!!

经反复测试发现System.Environment.CurrentDirectory确实是获取当前目录没错,但是如果A程序调用B程序 B程序里使用了System.Environment.CurrentDirectory获取目录。那么这个B程序里获取的这个目录就不再是B的应用程序所在目录了;而变成了A所在的目录了。这也就不难发现我在开机时弹出的目录是C:\Windows\System32 因为开机自启动程序也是由windows的某个进程调用的。

当遇到这样的情况时,我自己的解决方案是:

把所有System.Environment.CurrentDirectory改成System.AppDomain.CurrentDomain.BaseDirectory。

网上也有很多人说针对winform可以改成Application.StartupPath。

C# WinForm中AppDomain.CurrentDomain.BaseDirectory与Application.StartupPath的区别示例如下:

    1. AppDomain.CurrentDomain.BaseDirectory 返回结果为: D:\xxx\
    Application.StartupPath 返回结果为: D:\xxx
    2. Application.StartupPath 只能用于WinForm窗体中,而AppDomain.CurrentDomain.BaseDirectory既可以用于WinForm窗体中,也可以用于类库DLL文件中。

posted @ 2020-11-16 20:30  左正  阅读(343)  评论(0编辑  收藏  举报