要對 .csproj 專案檔進行偵錯,其實是可行的(參考這篇很久以前的(官方文章)[https://devblogs.microsoft.com/visualstudio/debugging-msbuild-script-with-visual-studio/]),但是有些時候,我們只是想輸出變數的值,在建置過程中稍微檢查一下專案檔的設定或變數值,這篇來看一下怎麼做。
專案檔基本概念
我們常見到的 .csproj 專案檔,就是交給 MSBuild.exe (Microsoft Build Engine) 這隻程式讀取並執行建置的。而這個以 XML 為基礎所撰寫出來的專案檔,有一些基本結構要先認識一下,主要的元素結構會長的像下面這樣:
1 | Project |
其中特別要知道的元素用途如下:
Property用來管理建置過程中會使用到的變數Item用來識別建置過程中的輸入值,例如程式碼檔案名稱、路徑等等Target、Task用來提供給 MSBuild 要如何執行建置程序
專案檔的內容還有很多細節,詳請參考瞭解專案檔這份官方文件。
關於輸出訊息
知道專案檔的結構後,不難發現要在哪裡處理輸出訊息,關鍵就是在 Target、Task 這兩個元素中。Target 可以看成較大的執行區塊,而 Task 則是某一個執行動作。
因此我們可以在專案檔中寫一個 Target 標籤,然後從MSBuild 工作參考這份官方文件種,找到預設所有可以使用的 Task,例如 Message。
Message 這個 Task 使用方式相當簡單 <Message Text="$(TestProperty)" Importance="high"/>,其中 Importance 是在指定訊息的重要性,可以是 high、normal 或 low,預設值是 normal。在一些輸出視窗中,會使用這個屬性來調整輸出的顏色。
所以如果要在 MSBuild 執行的過程中,將專案檔內的資訊輸出,則可以參考以下寫法:
1 | <Project Sdk="Microsoft.NET.Sdk"> |
輸出結果如下:
1 | Property Value |
這樣當碰到一些建置過程中用到的預設變數時,例如 $(Configuration)、$(BaseOutputPath)、$(VisualStudioVersion) 等專案屬性的值,就可以藉此輸出出來,方便確定建置過程的正確性。
如果想知道 MSBuild 預設會有那些變數和專案屬性,可以參考這份一般 MSBuild 專案屬性官方文件。
本篇完整範例程式碼請參考 poychang/output-project-variable-from-msbuild。
後記
關於 Target 還有一件很重要的設定,就是甚麼時候執行。
由於 Target 只會被 MSBuidl 執行一次,在過去 .NET Framework 的時代,我們可以直接把 Target Name 設定成預設的名字,例如 Build、Compile 等(更多 Target 預設名字請參考MSBuild 目標),來覆蓋原本的行為(因為後者覆蓋前者)。
到了 .NET (.NET Core)時代,專案檔已經改用 SDK 風格的寫法,因此你無法直接覆蓋,而是建議你使用 AfterTargets 和 BeforeTargets 兩個屬性來將你的 Target 加到指定執行順序中,例如上面的範例就是在 Build 之後執行。
如果你真的要覆蓋某一個 Target 的時候,可以參考以下寫法:
1 | <Project> |
之所以這樣會可行,是因為你寫的 Target 會在 Sdk.targets 之後執行,所以可以覆蓋掉預設的行為。
參考資料: