每次專案建置都沒問題,但只要更換開發環境時(例如:換一台電腦時使用不同版本的Visual Studio,或更換Jenkins Node),建置就會失敗,出現找不到Microsoft.WebApplication.targets的問題嗎?在此有個一勞永逸的方法可以解決這個問題,但解決問題前,首先要先了解問題所在。
Project.csproj定義
使用Visual Studio建立專案時,在專案根目錄會產生一個名為”專案名稱.csproj”的檔案,裡面會產生各種宣告,告訴MSBuild該引用那些檔案,當中就包括Microsoft.WebApplication.targets,它定義了.Net的封裝與MSDeployPublish的工作。
為何會找不到Microsoft.WebApplication.targets?
在建立或重建方案時,Visual Studio會自動偵測有無缺失WebApplication.targets並做出調整,若找不到引用項目就會自動加入自身版本的.targets路徑,這就是問題所在,請看以下圖片:
看起來好像只有v14跟v15的差別,現在來看看兩個版本的實際檔案在哪:
可以看到兩邊的路徑從Program Files (x86)開始就差了十萬八千里遠,這是因為每一版Visual
Studio的MSBuild版本都不一樣,對於自身引用的保留參數也都不一樣,$(MSBuildExtensionsPath32)這個參數就會指向不同地方,因此雖然這一個Node可以建置成功,但只要另一個Node沒有安裝同一個版本的Visual Studio,建置就會失敗。
解決方法
此方法可以在不開啟IDE的情況下解決目前主流版本(vs2010 – 2019,更舊或更新的版本不保證有效)的MSBuild引用WebApplication.targets的問題,且此方法與讓Visual
Studio自動生成.targets的差別在於不會產生一堆backup檔案,因為每一次自動生成,Visual Studio都會將舊版備份起來,版控就會很混亂,也會浪費許多空間。
解法就是直接在.csproj刪除原本的import WebApplication.targets並新增這兩行:
<Import
Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\WebApplications\Microsoft.WebApplication.targets"
Condition="'$(VisualStudioVersion)'<'15.0'" />
<Import
Project="$(MSBuildToolsPath)\..\..\Microsoft\VisualStudio\V$(VisualStudioVersion)\WebApplications\Microsoft.WebApplication.targets"
Condition="'$(VisualStudioVersion)'>='15.0'" />
微軟從Visual Studio 2017開始,將MSBuild依附於IDE,不再直接寫入環境參數,目的是提高MSBuild的版本共存性,因此我們用Visual Studio
2017(MSBuild 15)當作分水嶺,分別指定不同的路徑,再使用$(VisualStudioVersion)決定版本號,達到不開啟IDE就可以解決import失敗的效果。
參考資料
WebApplication.targets
usage:
MSBuild
15 new feature:
https://docs.microsoft.com/zh-tw/visualstudio/msbuild/what-s-new-in-msbuild-15-0?view=vs-2017