[英]C# console application not running stand-alone after being published
我對 C# 和 Visual Studio 比較陌生。
我遇到的問題是在我在 Visual Studio 中發布我的 C# 控制台應用程序之后。 控制台應用程序未正確處理擴充並拋出錯誤。
我已經設置了一些啟動配置文件來測試控制台應用程序在不同 arguments 下的行為方式。當我運行調試和發布配置文件時,它們都通過並給我預期的結果。
但是,當我 go 發布時,我 select 自包含和 select 生成單個文件。 (已發布的配置文件設置。)該應用程序不再按預期運行。
我收到以下錯誤:
Generic Exception Handler: System.ArgumentNullException: Value cannot be null. (Parameter 'paths')
at System.IO.Path.Combine(String[] )
at AMP_New_Project.AMP_New_Project_Folder.Main(String[] args) in C:\Users\eriskedahl\Documents\GitHub\JMS\NewAMP_Proj_Console\AMP_New_Proj.cs:line 135
PS C:\Users\erisk\Documents\GitHub\JMS\NewAMP_Proj_Console\Releases>
現在錯誤本身很好,看起來我的異常處理正在工作,但我有一個調試配置文件來檢查它並且允許路徑為 null。有一個 if 語句來處理未提供路徑參數時發生的情況.
if (strWorkPath == null || strWorkPath.Length == 0)
{
strWorkPath = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location)!;
}
控制台應用程序似乎不是獨立的,缺少一些參考資料,但不確定還有什么地方可以檢查。 為什么應用程序在發布后會有不同的行為?
當我運行調試且未提供路徑時,變量 strWorkPath 為 null,然后設置為控制台應用程序的當前工作目錄。
如前所述,當我通過 Visual Studio 中的調試運行應用程序時,這完全可以正常工作,正如預期的那樣,我只在運行已發布的版本時才會收到此錯誤。 如果我將 Powershell 或 cmd window 和 go 打開到 Bin/Release 文件夾並從那里運行應用程序,我也會得到預期的結果。 一旦我將 exe 文件復制到不同的文件夾,應用程序就會失敗。
當作為單個文件發布時,構建系統將構成應用程序的所有程序集捆綁在一起。
在 .NET 5 及之后的版本中,對於捆綁程序集,返回值為空字符串。
所以我們將一個空字符串傳遞給Path.GetDirectoryName
,它說:
path
的目錄信息,如果 path 表示根目錄或為null
,則為 null。
所以這可能就是正在發生的事情: Assembly.Location
返回一個空字符串,因為該程序集已作為發布的一部分與大量其他程序集捆綁在一起,並且Path.GetDirectoryName
將其轉換為null
。
要以支持捆綁的方式獲取應用程序的位置,請使用AppDomain.CurrentDomain.BaseDirectory
。
請注意,這不是當前工作目錄。 CWD 是用戶運行您的應用程序時所在的目錄。 通常假設如果用戶將相對路徑傳遞給您的應用程序(例如,作為命令行參數),應用程序應該將其解釋為相對於用戶的 CWD。
問題不在於您使用的是獨立部署,而是您還使用單文件部署(復選框之一)。
單文件部署和可執行文件的文檔提到某些Assembly
API 將無法在單文件部署模式下工作,包括Location
,它將返回一個空字符串:
API | 筆記 |
---|---|
Assembly.CodeBase |
拋出System.PlatformNotSupportedException 。 |
Assembly.EscapedCodeBase |
拋出System.PlatformNotSupportedException 。 |
Assembly.GetFile |
拋出System.IO.IOException 。 |
Assembly.GetFiles |
拋出System.IO.IOException 。 |
Assembly.Location |
返回空字符串。 |
AssemblyName.CodeBase |
返回null 。 |
AssemblyName.EscapedCodeBase |
返回null 。 |
Module.FullyQualifiedName |
返回值為<Unknown> 的字符串或拋出異常。 |
Marshal.GetHINSTANCE |
返回 -1。 |
Module.Name |
返回值為<Unknown> 的字符串。 |
這導致Path.GetDirectoryName
返回null
。
提到了一些解決方法:
要訪問可執行文件旁邊的文件,請使用System.AppContext.BaseDirectory
要查找可執行文件的文件名,請使用System.Environment.GetCommandLineArgs
的第一個元素,或從 .NET 6 開始,使用System.Environment.ProcessPath
中的文件名。
為避免完全運送松散的文件,請考慮使用嵌入式資源。
所以你可以使用System.AppContext.BaseDirectory
來確定目錄。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.