簡體   English   中英

C# 控制台應用程序在發布后無法獨立運行

[英]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 文件復制到不同的文件夾,應用程序就會失敗。

當作為單個文件發布時,構建系統將構成應用程序的所有程序集捆綁在一起。

Assembly.Location文檔說:

在 .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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM