從 .NET Framework 時代開始,我都用這招取得執行中的 EXE 路徑:

Assembly.GetExecutingAssembly().Location

最近發現這做法在 .NET Core / .NET 6 可能會出問題。用以下範例程式重現問題:

var execAsm = System.Reflection.Assembly.GetExecutingAssembly();
Console.WriteLine($"GetExecutingAssembly() Check");
Console.WriteLine($"FullName = {execAsm.FullName}");
Console.WriteLine($"Location = {execAsm.Location}");

dotnet run 沒什麼問題,顯示為 exec-asm.dll,但 dotnet publish 輸出 exe,結果跟我想得不一樣,呼叫 exec-asm.exe,GetExecutingAssembly() 仍指向 exec-asm.dll:

當使用單檔部署模式(dotnet publish -c Release -r win-x64 --no-self-contained -p:PublishSignleFile=true) 會出現更奇妙的結果,Location 傳回空字串:(之前介紹 .NET 5 單一檔案部署功能便提過「在單檔部署模式下某些 API 行為會改變或無法使用,包含:Assembly.Location 傳回空字串 (可改用 AppContext.BaseDirectory 取代)」,但我忘了)

.NET 6 超貼心,編譯警示直接提醒你改用 System.AppContext.BaseDirectory,但如果要知道 exe 檔名稱,.NET 6 有個替代 API Process.GetCurrentProcess().MainModule.FileName 或是 Environment.ProcessPath,將程式修改為:

using System.Diagnostics;

Console.WriteLine(@$"System.AppContext.BaseDirectory
 * {System.AppContext.BaseDirectory}");
Console.WriteLine(@$"Process.GetCurrentProcess().MainModule.FileName 
 * {Process.GetCurrentProcess().MainModule?.FileName}");

成功!

Example of getting the path of .NET Core/6 exe files.


Comments

Be the first to post a comment

Post a comment