「目前路徑」在不同執行環境(主控台、WinForms、WPF、ASP.NET Core、Windows Service、單一檔案發布)代表完全不同的含義。本文整理 7 種常見 API、適用場景、回傳值差異與最佳實務,附表格速查。
| API | 命名空間 | 回傳範例 (主控台/WinForms) | 含義 | 適用場景 |
|---|---|---|---|---|
Process.GetCurrentProcess().MainModule.FileName | System.Diagnostics | C:\App\MyApp.exe | 目前進程執行檔完整路徑 | 需知自身執行檔位置(自更新、啟動參數) |
Environment.CurrentDirectory | System | C:\App | 進程啟動時的工作目錄 (可讀寫) | 相對路徑解析基準,可被改變 |
Directory.GetCurrentDirectory() | System.IO | C:\App | 同上,靜態方法風格 | 同上,慣用於 IO 操作 |
AppDomain.CurrentDomain.BaseDirectory | System | C:\App\ | 應用程式基底目錄 (含尾斜線) | 尋找同目錄下的設定檔、DLL、資源檔 |
Application.StartupPath | System.Windows.Forms | C:\App | WinForms 應用程式啟動目錄 (無尾斜線) | 僅限 WinForms,相容 .NET Framework |
Application.ExecutablePath | System.Windows.Forms | C:\App\MyApp.exe | WinForms 執行檔完整路徑 | 同上 |
AppDomain.CurrentDomain.SetupInformation.ApplicationBase | System | C:\App\ | 等同 BaseDirectory | 進階 AppDomain 設定場景 |
// .NET 6+ PublishSingleFile=true
// MainModule.FileName → 臨時解壓路徑 (如 /tmp/.net/MyApp/xyz/MyApp)
// AppDomain.BaseDirectory → 同臨時目錄
// 解決:使用 Assembly.Location (可能為空) 或 IHostEnvironment.ContentRootPath (ASP.NET Core)
// Program.cs
var builder = WebApplication.CreateBuilder(args);
// 建議注入 IWebHostEnvironment / IHostEnvironment
app.MapGet("/path", (IWebHostEnvironment env) =>
new { ContentRoot = env.ContentRootPath, WebRoot = env.WebRootPath });
ContentRootPath:專案根目錄 (含 appsettings.json)WebRootPath:wwwroot 靜態檔案目錄C:\Windows\System32,不可信任。AppDomain.BaseDirectory 或 IHostEnvironment.ContentRootPath 定位資源。
// WPF
System.IO.Path.GetDirectoryName(System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName)
// 或
AppDomain.CurrentDomain.BaseDirectory
// UWP/MAUI (沙盒)
Windows.Storage.ApplicationData.Current.LocalFolder.Path // 本地資料
Windows.ApplicationModel.Package.Current.InstalledLocation.Path // 安裝目錄 (唯讀)
public interface IAppPathService
{
string ExecutablePath { get; } // 執行檔完整路徑
string ExecutableDirectory { get; } // 執行檔所在目錄 (含尾斜線)
string WorkingDirectory { get; } // 目前工作目錄
string ContentRoot { get; } // 內容根目錄 (設定檔、資源)
}
public class AppPathService : IAppPathService
{
private readonly string _exePath;
private readonly string _exeDir;
private readonly string _contentRoot;
public AppPathService()
{
_exePath = Process.GetCurrentProcess().MainModule.FileName;
_exeDir = Path.GetDirectoryName(_exePath) + Path.DirectorySeparatorChar;
// 單一檔案發布修正
if (string.IsNullOrEmpty(Assembly.GetEntryAssembly()?.Location) ||
_exeDir.Contains("tmp") || _exeDir.Contains("Temp"))
{
_exeDir = AppDomain.CurrentDomain.BaseDirectory;
}
_contentRoot = _exeDir; // 預設同目錄,ASP.NET Core 可覆寫注入
}
public string ExecutablePath => _exePath;
public string ExecutableDirectory => _exeDir;
public string WorkingDirectory => Environment.CurrentDirectory;
public string ContentRoot => _contentRoot;
}
Path.Combine、Path.GetFullPath,拒絕字串拼接。Path.DirectorySeparatorChar / Path.AltDirectorySeparatorChar。LongPathsEnabled (登錄表/Group Policy) 或使用 \\?\ 前綴。Program Files、System32 需管理員;優先寫入 Environment.GetFolderPath(SpecialFolder.LocalApplicationData)。IAppPathService,測試時用 Mock 指定臨時目錄。Process.GetCurrentProcess().MainModule.FileName (修正單一檔案)AppDomain.CurrentDomain.BaseDirectory / IHostEnvironment.ContentRootPathEnvironment.GetFolderPath(SpecialFolder.LocalApplicationData)Path.GetTempPath()IWebHostEnvironment.WebRootPath沒有萬用的「目前路徑」,只有正確的「語境路徑」。建立專案專屬的 IAppPathService,在啟動時一次解析並修正單一檔案/服務/容器環境差異,後續全程依賴注入使用,即可徹底消除路徑相關 Bug。