在 .NET 專案開發中,隨著專案複雜性增加,相依的 dll 檔案也會逐漸增多。這往往導致輸出目錄混亂,不便於管理與部署。而 NetBeauty2 開源專案正是為了解決此問題而生,它能幫助開發者在獨立發佈 .NET 專案時,將 .NET 執行階段與相依的 dll 檔案移動到指定目錄,從而讓輸出目錄更乾淨、清爽。
1. NetBeauty2 簡介
NetBeauty2 是一個開源的 .NET 相依程式庫整理工具,其主要作用是在 .NET 專案獨立發佈時,對輸出目錄進行整理與最佳化。透過 NetBeauty2,開發者可以輕鬆地將 .NET 執行階段與相依的 dll 檔案移動到指定目錄,使得專案的輸出目錄更加清晰、易於管理。
專案倉庫位址:https://github.com/nulastudio/NetBeauty2
下圖為最佳化後輸出目錄(.NET 執行階段及引用相依程式庫移到 libraries 目錄,目錄名稱可設定):

下圖為極限最佳化後輸出目錄(檢視 --hiddens 選項使用方式)

再來對比未使用前的輸出目錄(震撼吧!.NET 執行階段及相關相依程式庫全放在根輸出目錄,.NET Framework 可以設定 privatePath,.NET Core 可沒那麼方便):

2. 支援情況
| NetBeauty 2 | NetCoreBeauty | |
|---|---|---|
| 支援框架 | .NET Framework .NET Core 3.0+ |
.NET Core 2.0+ |
| 支援部署模式 | Framework-dependent deployment (FDD) Self-contained deployment (SCD) Framework-dependent executables (FDE) |
Self-contained deployment (SCD) |
| 支援作業系統 | 全部 | win-x64 win-x86 win-arm64(.NET 6+) linux-x64 linux-arm linux-arm64 osx-x64 osx-arm64(.NET 6+) |
| 是否需要修補 HostFXR | 否 是(若使用修補) | 是 |
| 最小結構 | ~20 個檔案 ~8 個檔案(若使用修補) | ~8 個檔案 |
| 運作方式 | STARTUP_HOOKS AssemblyLoadContext.Resolving AssemblyLoadContext.ResolvingUnmanagedDll + patched libhostfxr(若使用修補) additionalProbingPaths(若使用修補) |
patched libhostfxr additionalProbingPaths |
| 共用執行階段 | 是 | 可能(如果單獨使用 patched libhostfxr) |
3. 如何使用?
3.1. 準備工作
在你的 .NET Core 專案(需要發佈的主專案)新增 NuGet 套件:
dotnet add package nulastudio.NetBeauty
開啟專案檔編輯(.csproj):
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.0</TargetFramework>
</PropertyGroup>
<PropertyGroup>
<BeautySharedRuntimeMode>False</BeautySharedRuntimeMode>
<!-- beauty into sub-directory, default is libs, quote with "" if contains space -->
<BeautyLibsDir Condition="$(BeautySharedRuntimeMode) == 'True'">../libraries</BeautyLibsDir>
<BeautyLibsDir Condition="$(BeautySharedRuntimeMode) != 'True'">./libraries</BeautyLibsDir>
<!-- dlls that you don't want to be moved or can not be moved -->
<!-- <BeautyExcludes>dll1.dll;lib*;...</BeautyExcludes> -->
<!-- dlls that end users never needed, so hide them -->
<!-- <BeautyHiddens>hostfxr;hostpolicy;*.deps.json;*.runtimeconfig*.json</BeautyHiddens> -->
<!-- set to True if you want to disable -->
<DisableBeauty>False</DisableBeauty>
<!-- set to False if you want to beauty on build -->
<BeautyOnPublishOnly>False</BeautyOnPublishOnly>
<!-- DO NOT TOUCH THIS OPTION -->
<BeautyNoRuntimeInfo>False</BeautyNoRuntimeInfo>
<!-- set to True if you want to allow 3rd debuggers(like dnSpy) debugs the app -->
<BeautyEnableDebugging>False</BeautyEnableDebugging>
<!-- the patch can reduce the file count -->
<!-- set to False if you want to disable -->
<!-- SCD Mode Feature Only -->
<BeautyUsePatch>True</BeautyUsePatch>
<!-- App Entry Dll = BeautyDir + BeautyAppHostDir + BeautyAppHostEntry -->
<!-- see https://github.com/nulastudio/NetBeauty2#customize-apphost for more details -->
<!-- relative path based on AppHostDir -->
<!-- .NET Core Non Single-File Only -->
<!-- <BeautyAppHostEntry>bin/MyApp.dll</BeautyAppHostEntry> -->
<!-- relative path based on BeautyDir -->
<!-- .NET Core Non Single-File Only -->
<!-- <BeautyAppHostDir>..</BeautyAppHostDir> -->
<!-- <BeautyAfterTasks></BeautyAfterTasks> -->
<!-- valid values: Error|Detail|Info -->
<BeautyLogLevel>Info</BeautyLogLevel>
<!-- set to a repo mirror if you have troble in connecting github -->
<!-- <BeautyGitCDN>https://gitee.com/liesauer/HostFXRPatcher</BeautyGitCDN> -->
<!-- <BeautyGitTree>master</BeautyGitTree> -->
</PropertyGroup>
<ItemGroup>
<PackageReference Include="nulastudio.NetBeauty" Version="2.1.4.4" />
</ItemGroup>
</Project>
執行 dotnet build 或 dotnet publish,最佳化輸出操作會自動完成。
3.2. 如果應用已經發佈?
如果你的應用程式已經發佈,可以這樣使用(站長沒試過,這可以作為發佈後的補償措施):
Usage:
nbeauty2 [--loglevel=(Error|Detail|Info)] [--srmode] [--enabledebug] [--usepatch] [--hiddens=hiddenFiles] [--noruntimeinfo] [--roll-forward=<rollForward>] [--apphostentry=<appHostEntry>] [--apphostdir=<appHostDir>] <beautyDir> [<libsDir> [<excludes>]]
例如:
ncbeauty2 --usepatch --loglevel Detail --hiddens "hostfxr;hostpolicy;*.deps.json;*.runtimeconfig*.json" /path/to/publishDir libraries "dll1.dll;lib*;..."
3.3. 設定為 .NET Core 全域工具
dotnet tool install --global nulastudio.nbeauty
安裝後在程式發佈時會自動套用。
4. 各種專案使用範例
複製倉庫(https://github.com/nulastudio/NetBeauty2),裡面有各種範本專案使用範例:

| 測試專案名 | 說明 |
|---|---|
| WPFTest | WPF 專案(Winform 類似),預設 .NET 5 |
| WebAppTest | RazorPages 專案,預設 .NET 6 |
| NetFxTest | .NET Framework WPF 專案(.NET 4.x,Winform 類似) |
| ChromelyTest | 引用了 Chromely 的 .NET 專案 |
| AvaloniaTest | Avalonia UI 專案,預設 .NET 5 |
小知識 1
Chromely NuGet 套件是一個用於建立跨平台桌面應用程式的程式庫,它提供了一個基於 Chromium 的瀏覽器控制項。透過 Chromely,開發者可以使用 Web 技術(如 HTML、CSS 和 JavaScript)來建構桌面應用程式的使用者介面,同時保留對本機系統資源的存取。
Chromely NuGet 套件提供了一套完整的 API 與工具,使得開發者可以輕鬆地將 Web 應用程式轉換為桌面應用程式,而無需進行大量的程式碼重寫或修改。它還支援各種外掛程式與擴充功能,以便開發者可以根據需要新增額外的功能或自訂現有的功能。
此外,Chromely 還支援多種程式語言與框架,如 C#、.NET Core、ASP.NET Core 等,這使得開發者可以選擇他們最熟悉的技術堆疊來建構應用程式。
小知識 2
Avalonia UI 是一個跨平台的 .NET UI 框架,它允許開發者使用 XAML 與 C# 語言建立可在多個平台上執行的應用程式,包括 Windows、Linux、macOS、iOS、Android 以及 WebAssembly。Avalonia UI 旨在幫助開發者建構美觀、現代的圖形使用者介面 (GUI)。它相容於所有支援 .NET Standard 2.0 的平台,使開發者能夠從單一程式碼庫建立適用於多個作業系統的原生應用程式。透過使用 Avalonia UI,開發者可以充分利用 .NET 生態系統的強大功能,同時實現跨平台相容性,降低開發成本並提高開發效率。
5. 總結
林德熙大佬分享過類似的套件 NuGet Gallery | dotnetCampus.PublishFolderCleaner 3.11.1,但該套件說明只在 Windows 發佈時支援,大家可以比較使用,原文連結:PublishFolderCleaner 讓你的 dotnet 應用發佈資料夾更加整潔 - lindexi - 部落格園 (cnblogs.com),再次給出本文介紹的套件 NetBeauty2 開源位址:
專案倉庫位址:https://github.com/nulastudio/NetBeauty2
參考: