警惕使用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文件中。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM