PublishFolderCleaner 讓你的 dotnet 應用發布文件夾更加整潔

大家都知道,在 dotnet 發布時,將會在輸出的 publish 文件夾包含所需的依賴。在 .NET Core 開始,引入了 AppHost 的概念,即使是單個程式集,也需要獨立的 Exe 可執行文件帶上實際包含 Main 函數的 dll 文件。特別是進行獨立發布的時候,輸出文件夾上有超級多個文件,看起來不清真。本文來告訴大家如何使用 PublishFolderCleaner 工具讓發布文件夾只留一個 Exe 和一個 Lib 文件夾

使用方法

使用方法十分簡單,只需要安裝 dotnetCampus.PublishFolderCleaner 庫即可。編輯入口項目的 csproj 文件,添加如下程式碼

  <ItemGroup>
    <PackageReference Include="dotnetCampus.PublishFolderCleaner" Version="3.0.3" />
  </ItemGroup>

接下來就和之前一樣發布即可,不影響原有的發布步驟

效果

發布完成之後,打開發布文件夾,此時可以發現原本亂糟糟的文件夾被替換為只有一個 exe 可執行文件和一個 lib 文件夾。雙擊 exe 可執行文件即可獲得和之前一樣的效果

打開 Lib 文件夾,可以看到此文件夾裡面就是原本放在發布文件夾裡面的除了入口 exe 之外的其他文件

以上的 PublishFolderCleaner 工具的作用就是將發布文件夾裡面的所有文件,除了入口 exe 之外的文件,都放入到 lib 文件夾裡面,然後修改入口 exe 文件的邏輯,讓入口 exe 可以從 lib 文件夾裡面讀取入口 dll 文件,從而實現此功能

例子

我創建了一個基於 .NET 5 的 WPF 應用,給此應用加上 dotnetCampus.PublishFolderCleaner 的 NuGet 包

接著使用命令行進行發布,發布命令如下

dotnet publish -r win-x64 -c release --self-contained

接著進入到 bin\Release\net5.0-windows\win-x64\publish\ 文件夾,可以看到此文件夾只有存放一個 exe 和一個 lib 文件夾,如下

|   WhihuqeabaLeelurlallball.exe
|   
\---lib
    |   clrcompression.dll
    |   clretwrc.dll
    |   clrjit.dll
    |   coreclr.dll
    |   createdump.exe
    |   WhihuqeabaLeelurlallball.deps.json
    |   WhihuqeabaLeelurlallball.dll
    |   WhihuqeabaLeelurlallball.pdb
    |   WhihuqeabaLeelurlallball.runtimeconfig.json
    |   WindowsBase.dll
    |   WindowsFormsIntegration.dll
    |   wpfgfx_cor3.dll
    |   // 忽略很多文件
    +---zh-Hans
    |       Microsoft.VisualBasic.Forms.resources.dll
    |       PresentationCore.resources.dll
    |       // 忽略很多文件
    |       
    \---zh-Hant
            Microsoft.VisualBasic.Forms.resources.dll
            // 忽略很多文件

程式碼

本文所有程式碼放在 githubgitee 歡迎訪問

可以通過如下方式獲取本文的源程式碼,先創建一個空文件夾,接著使用命令行 cd 命令進入此空文件夾,在命令行裡面輸入以下程式碼,即可獲取到本文的程式碼

git init
git remote add origin //gitee.com/lindexi/lindexi_gd.git
git pull origin 24c0c22f4a0bb292893ac09aba2f14b3b84a2d6e

以上使用的是 gitee 的源,如果 gitee 不能訪問,請替換為 github 的源

git remote remove origin
git remote add origin //github.com/lindexi/lindexi_gd.git

獲取程式碼之後,進入 WhihuqeabaLeelurlallball 文件夾

可以通過這個簡單的例子試試效果

原理

本文使用的 PublishFolderCleaner 工具,在 GitHub 上完全開源,屬於我所在團隊構建工具鏈的工具,請看 //github.com/dotnet-campus/dotnetcampus.DotNETBuildSDK

核心機制就是添加構建調度步驟,在發布之後執行移動文件和修改入口 exe 兩個步驟

其中添加構建調度的邏輯程式碼如下

<Project>
  <Target Name="MoveThePublishFolderToLibFolder" AfterTargets="Publish">

    <PropertyGroup>
      <PublishFolderCleanerCommandArgs>dotnet "$(MSBuildThisFileDirectory)..\tools\net5.0\PublishFolderCleaner.dll" -p "$(PublishDir) " -a "$(AssemblyName)"</PublishFolderCleanerCommandArgs>
    </PropertyGroup>

    <Exec Command="$(PublishFolderCleanerCommandArgs)"></Exec>
  </Target>
</Project>

也就是在發布完成之後,通過 dotnet 命令調用 PublishFolderCleaner 工具,如上面程式碼可以看到這是一個 .NET 5 的工具,要求當前開發者的開發環境裡面安裝有 .NET 5 才能執行此工具

在 PublishFolderCleaner 工具裡面完成如上兩個步驟,將原有的放在發布文件夾裡面的文件全部放入到裡層的 lib 文件夾,再通過修改入口 exe 可執行文件,也就是 AppHost 文件,讓入口 exe 從原本的相同文件夾讀取入口 dll 替換為從 lib 文件夾裡面讀取入口 dll 文件

關於修改 AppHost 文件的知識,請參閱 dotnet core 應用是如何跑起來的 通過AppHost理解運行過程dotnet 桌面端基於 AppHost 的配置式自動切換更新後的應用程式路徑