3

體驗 .NET 5 單一檔案部署功能

 3 years ago
source link: https://blog.darkthread.net/blog/net5-single-file-deployment/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

體驗 .NET 5 單一檔案部署功能

2021-01-25 08:40 PM 0 2,105

前幾天聊到我喜歡將小工具程式編譯成單一檔案,免安裝,不必解壓縮 DLL,整個工具就一個 EXE 檔,放到桌面上點兩下就能用,這是最棒的部署方式! 文章裡提到 .NET 5 內建嵌入參照 DLL 功能,且不像 .NET Core 3.1 得將內嵌參照 DLL 寫成實體檔暫存,實現真正的單檔執行。這篇文章會實際體驗 .NET 5 的單檔編譯功能。

好孩子要先看操作說明書,MSDocs 文件 - Single file deployment and executable 的說明很完整,摘要重點如下:

  1. .NET Core/.NET 5 程式有兩種打包模式:Framework-Depedent Deployment Model (執行環境已安裝 .NET Core/.NET 5 Runtime 或 SDK) 以及 Self-Contained Appliations (自備 Runtime DLL,執行環境不用預先裝 .NET Core/.NET 5 Runtime 或 SDK,但檔案數很多,體積也大,50MB 起跳)。這兩種模式都支援單檔輸出,也支援 ReadyToRun (預先完成 JIT 編譯,可加快程式啟動速度,但必須先確認部署對象為 Linux/Windows/macOS、x86/x64/ARM,啟用 R2R 後 EXE 檔案會變大)。而 .NET 5 還支援實驗性質的 Trim 功能,可偵測並排除 Self-Contained Applictation 沒用到 Runtime 或 Framework DLL 減少資料量。
  2. 在單檔部署模式下某些 API 行為會改變或無法使用,包含:
    • Assembly.Location 傳回空字串 (可改用 AppContext.BaseDirectory 取代)
    • Module.FullQualfieldName 傳回 <Unknown> 或抛出例外
    • Mudule.Name 傳回 <Unknown>
    • Assembly.GetFile、Assembly.GetFiles 抛出 IOException
    • Assembly.CodeBase、Assembly.EscapedCodeBase 抛出 PlatformNotSupportedException.
    • AssemblyName.CodeBase、AssemblyName.EscapedCodeBase 傳回 null
  3. Self-Contained Single-File 模式需額外提供 mscordbi.dll/mccordbi.so 以進行偵錯
  4. 單檔部署預設不包含原生 DLL,但有個旗標 IncludeNativeLibrariesForSelfExtract 可將原生 DLL 也嵌入 EXE,執行時再解到暫存目錄使用。
  5. PDB 檔預設獨立存在,在 csproj 設定 <DebugType>embedded</DebugType> 可將它也併進 EXE。
  6. 透過 csproj <ExcludeFromSingleFile>true</ExcludeFromSingleFile> 可排除特定 DLL 不要內嵌

背景知識學完開始實際演練。以下以 Visual Studio 2019 為例,主要控制介面在 Publish Profile 的 Configuration 設定:

Target framework 選 net5.0
Deployment mode 可選 Self-contained 或 Framework-dependent
Target runtime 則依要部署的作業系統選 win-x86、win-x64、linux-x64... 等等

下方 File publish options 是重點:

Produce single files 是否啟用單檔部署(將參照 DLL 包進 EXE 檔)?
Enable ReadyToRun complication 是否啟用 R2R?
Trim unused assemblies (只適用單檔部署)是否排除沒用到的 Runtime 或 Framework DLL?

實測不同選項的效果,以 Self-Contained 模式為例,若不開啟單檔部署,編譯輸出檔案數高達 233 個(含 EXE、DLL、JSON 檔):

啟用單檔部署後,大部分檔案都已併入 Net5SingleFile.exe,e_sqlite3.dll 是 SQLite 的原生 DLL,預設不會包進去,另外還有幾個檔案 clrcompression.dll、clrjit.dll、coreclr.dll、mscordaccore.dll 是 .NET 5 Runtime / Framework 用到的原生 DLL:

開啟 ReadyToRun 後,Net5SingleFile.exe 變胖 (由 53,988KB 增加到 54,945KB):

啟用 Trim unused assemblies,Net5SingleFile.exe 縮小到 44,664 KB:

為了實現真正的單一檔案,修改 csproj 加入 IncludeNativeLibrariesForSelfExtract、DebugType true,達成一檔獨大 66.6MB。(註:未開 Trim unused assemblies)

如果確定待部署環境有裝 .NET 5 Runtime 或 SDK,改用 Framework-dependent 模式,EXE 檔案可縮小到 7MB 有找。

體驗完 .NET 5.0 的單檔部署,系統內建就是不一樣,再加上 Visual Studio 的火力支援,操作比原本預期方便流暢,簡單! 快速! 好用到咩噗。整體使用下來,.NET 5.0 的成熟完整度令我驚喜,未來要開發小工具,我會優先考慮用 .NET 5.0 來寫。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK