本文主要介紹在使用 Visual Studio 進行偵錯和釋出時,如何在 .NET 計畫中復制資源資料夾到生成目錄。
1. 背景
在開發 .NET 計畫的過程中,我們有時會遇到需要在 debug 、 release 或是釋出時將資源資料夾復制到生成目錄的需求。這些資源可能包括圖片、配置檔、數據檔等。本文將以一個實際計畫為背景,教你如何透過修改計畫檔(.csproj 或 .vbproj)中的 MSBuild 指令來實作這個需求。
在我的計畫中,我正在測試和學習 SemanticKernel,這是一個強大的語意分析工具。其中的外掛程式(plugins)可以以配置檔的方式儲存,如下程式碼所示:
var plugin = kernel.CreatePluginFromPromptDirectory(Path.Combine("plugins", "TranslatePlugin"));
我們使用 VS Code 進行開發時,透過
dotnet run
命令可以方便地看到執行結果,而且沒有復制資料夾的問題。然而,如果改為使用 Visual Studio 進行開發,我們就需要解決資源資料夾在構建時的復制問題。
2. 方法一:逐個添加檔
我們首先可能想到的方法是在 Visual Studio 中手動添加資源資料夾中的檔。這種方法雖然簡單,但是當資源資料夾中的檔較多時,就會變得非常繁瑣。而且,每次添加新檔時,都需要重新操作一遍,雖然透過UI操作容易,但這顯然不是一個好的解決方案。
當我們設定完後,其會自動修改 .csproj(C# 計畫)檔內容,加入如下資訊:
<ItemGroup>
<NoneUpdate="plugins\TranslatePlugin\Basic\config.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
3. 方法二:添加 MSBuild 指令
在計畫檔中,我們可以將添加一個新的 MSBuild 目標來完成資源資料夾的復制任務。以下是添加的指令範例:
<ProjectSdk="Microsoft.NET.Sdk">
...
<TargetName="CopyResources"AfterTargets="AfterBuild">
<ItemGroup>
<ResourceFilesInclude="plugins\**"/>
</ItemGroup>
<CopySourceFiles="@(ResourceFiles)"DestinationFolder="$(OutDir)\plugins\%(RecursiveDir)"/>
</Target>
</Project>
在這個範例中,
CopyResources
是一個新的 MSBuild 目標,它在構建完成後執行(由
AfterTargets="AfterBuild"
指定)。
ItemGroup
定義了一個名為
ResourceFiles
的項,包含
plugins
資料夾下的所有檔和子資料夾。
Copy
任務則將這些檔復制到輸出目錄下的
plugins
資料夾。
這種方式雖然在偵錯可以正常工作,但是在釋出時,資源資料夾並不會被復制到釋出目錄。這是因為
AfterBuild
目標只在偵錯時執行,而在釋出時並不會執行。因此,我們需要再添加一個新的規則,將
AfterBuild
替換為
Publish
,同時需要調整輸出資料夾,修改
OutDir
為
PublishDir
以及規則名。這樣,就可以在釋出時復制資源資料夾。修改後需要多添加進計畫檔的資訊如下:
<TargetName="CopyResourcesPublish"AfterTargets="Publish">
<ItemGroup>
<ResourceFilesInclude="plugins\**"/>
</ItemGroup>
<CopySourceFiles="@(ResourceFiles)"DestinationFolder="$(PublishDir)\plugins\%(RecursiveDir)"/>
</Target>
3. 方法三:使用通配符
比較上述兩種方法,我們可以發現,手動添加檔和添加 MSBuild 指令都需要指定資源資料夾中的檔或是需要重復設定,這樣顯然不是一個好的解決方案。我們可以修改自動生成的那段程式碼,使用通配符來簡化這個過程。以下是使用通配符的範例:
<ItemGroup>
<NoneUpdate="plugins\**">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
這樣,我們就可以將
plugins
資料夾下的所有檔和子資料夾都復制到輸出目錄。這種方法簡單、直接,而且不需要手動添加檔,非常適合在資源資料夾中的檔較多時使用。
4. 結束語
上述方法提供了一種簡便的方式來在 .NET 計畫中復制資源資料夾,希望這也能幫助到遇到類似問題的你。當然在實際使用中我們可能還需遇到一些更加復雜的需求,比如排查部份,選擇包含等等,這些都可以透過類似的方式來實作。