四種方法獲取可執行程式的文件路徑(.NET Core / .NET Framework)

  • 2020 年 2 月 10 日
  • 筆記

本文介紹四種不同的獲取可執行程式文件路徑的方法。適用於 .NET Core 以及 .NET Framework。


使用程式集資訊獲取

var executablePath = Assembly.GetEntryAssembly().Location;

這種方式的思路是獲取入口程式集所在的路徑。不過 Assembly.GetEntryAssembly() 能獲取到的程式集是入口託管程式集;使用此方法會返回第一個託管程式集。

只有 .NET Framework 程式的入口才是託管程式(exe)。而對於 .NET Core 程式,如果直接發布成帶環境依賴聲明的 dll,那麼實際運行的進程是 dotnet.exe;而如果發布成自包含的 exe 程式,其主 exe 也是一個非託管的 CLR 啟動器而已,並不是託管程式集。

所以此方法適用條件:

  1. 必須是 .NET Framework 程式(.NET Core 程式不適用)

使用應用程式域資訊獲取

var executablePath = AppDomain.CurrentDomain.SetupInformation.ApplicationBase;

這種方式的思路是獲取當前 AppDomain 所在的文件夾。不過此方法也只是獲取到文件夾而已,不包含文件名。

所以此方法適用條件:

  1. 你不需要知道文件名,只是要一個程式所在的文件夾而已。

當然,此方法因為不涉及到託管和非託管程式集,所以與編譯結果無關,適用於 .NET Core 和 .NET Framework 程式。

使用進程資訊獲取

var executablePath = Process.GetCurrentProcess().MainModule.FileName;

這種方式的思路是獲取當前進程可執行程式的完全路徑。

對於 .NET Framework 程式,其 exe 就是這個路徑。

對於 .NET Core 程式來說:

  1. 如果發布成帶環境依賴聲明的 dll,那麼此方法獲取到的可執行程式名將是 dotnet.exe,這顯然不會是我們預期的行為;
  2. 如果發布成自包含的 exe,那麼此方法獲取到的可執行程式名就是程式自己的名稱,這是期望的結果。

所以此方法適用條件:

  1. 適用於 .NET Framework 程式;
  2. 適用於發布成自包含的 .NET Core 程式。

使用命令行參數獲取

我在另一篇部落格中提到命令行參數中包含應用程式路徑:

於是我們也可以通過命令行參數來獲取到可執行程式的路徑。

var executablePath = Environment.GetCommandLineArgs()[0];

這種方法的效果和前面使用進程資訊獲取的效果是相同的,會獲取到相同的可執行程式路徑。

總結靠譜的方法

通過以上方法的說明,我們可以知道目前沒有 100% 可靠的獲取當前可執行程式文件路徑的方法,不過可以組合多種方法達到 100% 可靠的目的。

  1. 如果我們只需要獲取程式所在的文件夾
    • 那麼請直接使用 AppDomain.CurrentDomain.SetupInformation.ApplicationBase
  2. 如果我們需要獲取到可執行程式的完整路徑
    • 先通過進程或者命令行參數的方式獲取
      • Process.GetCurrentProcess().MainModule.FileName
      • Environment.GetCommandLineArgs()[0]
    • 如果得到的進程是 dotnet.exe,那麼再通過程式集資訊獲取
      • Assembly.GetEntryAssembly().Location

另外,關於以上方法的性能對比,你可以參閱林德熙的部落格:dotnet 獲取路徑各種方法的性能對比

本文會經常更新,請閱讀原文: https://blog.walterlv.com/post/get-current-executable-file-path.html ,以避免陳舊錯誤知識的誤導,同時有更好的閱讀體驗。

本作品採用 知識共享署名-非商業性使用-相同