我在幫一個客戶 Code Review 並重構專案的時候,發現他們的專案在 Visual Studio 2019 都可以順利的建置專案,但是透過 Azure Pipelines 使用 MSBuild 建置卻會編譯失敗,錯誤訊息非常不清楚,真的是查了很久才想通問題的主因在哪裡,我覺得值得寫篇文章記錄一下。
錯誤訊息
發生建置失敗時,通常都是先透過 Log 找到蛛絲馬跡,首先映入眼簾的是「錯誤」訊息,總共有 68 個:
##[error]Common\Shared\CheckMod.cs(15,18): Error CS0234: The type or namespace name 'Mvc' does not exist in the namespace 'System.Web' (are you missing an assembly reference?)
##[error]Common\Utils\AzureStorage.cs(8,17): Error CS0234: The type or namespace name 'Azure' does not exist in the namespace 'Microsoft' (are you missing an assembly reference?)
##[error]Common\FTP\FtpUtils.cs(1,7): Error CS0246: The type or namespace name 'FluentFTP' could not be found (are you missing a using directive or an assembly reference?)
...
...
這錯誤很怪,我明明 NuGet Restore 都有成功,怎麼可能編譯時找不到命名空間呢?我在本機是可以編譯的啊!
一般來說,錯誤都解決不了,通常不會去找「警示」訊息,但我還是去看了,共有 30 個:
##[warning]C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\MSBuild\Current\Bin\Microsoft.Common.CurrentVersion.targets(2203,5): Warning MSB3245: Could not resolve this reference. Could not locate the assembly "AngleSharp, Version=0.14.0.0, Culture=neutral, PublicKeyToken=e83494dcdc6d31ea, processorArchitecture=MSIL". Check to make sure the assembly exists on disk. If this reference is required by your code, you may get compilation errors.
##[warning]C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\MSBuild\Current\Bin\Microsoft.Common.CurrentVersion.targets(2203,5): Warning MSB3245: Could not resolve this reference. Could not locate the assembly "AngleSharp.Css, Version=0.14.2.0, Culture=neutral, PublicKeyToken=e83494dcdc6d31ea, processorArchitecture=MSIL". Check to make sure the assembly exists on disk. If this reference is required by your code, you may get compilation errors.
##[warning]C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\MSBuild\Current\Bin\Microsoft.Common.CurrentVersion.targets(2203,5): Warning MSB3245: Could not resolve this reference. Could not locate the assembly "AntiXssLibrary, Version=4.3.0.0, Culture=neutral, PublicKeyToken=d127efab8a9c114f, processorArchitecture=MSIL". Check to make sure the assembly exists on disk. If this reference is required by your code, you may get compilation errors.
##[warning]C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\MSBuild\Current\Bin\Microsoft.Common.CurrentVersion.targets(2203,5): Warning MSB3245: Could not resolve this reference. Could not locate the assembly "EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL". Check to make sure the assembly exists on disk. If this reference is required by your code, you may get compilation errors.
...
...
他顯示 Check to make sure the assembly exists on disk 耶!但我的資料夾明明就有完整的 packages
目錄,套件也都有還原成功啊!
魔鬼總是出在細節裡,這段 Log 真的很難看出問題所在。我一開始只看出他「非常認真」的想找到 EntityFramework.dll
在哪裡,但最終就是找不到!
2021-09-08T09:59:25.0317073Z C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\MSBuild\Current\Bin\Microsoft.Common.CurrentVersion.targets(2203,5): warning MSB3245: Could not resolve this reference. Could not locate the assembly "EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL". Check to make sure the assembly exists on disk. If this reference is required by your code, you may get compilation errors. [D:\a\1\s\Common.csproj]
2021-09-08T09:59:25.0319856Z For SearchPath "{HintPathFromItem}".
2021-09-08T09:59:25.0320809Z Considered "D:\a\1\packages\EntityFramework.6.2.0\lib\net45\EntityFramework.dll", but it didn't exist.
2021-09-08T09:59:25.0321729Z For SearchPath "{TargetFrameworkDirectory}".
2021-09-08T09:59:25.0322812Z Considered "C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\EntityFramework.winmd", but it didn't exist.
2021-09-08T09:59:25.0324318Z Considered "C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\EntityFramework.dll", but it didn't exist.
2021-09-08T09:59:25.0326235Z Considered "C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\EntityFramework.exe", but it didn't exist.
2021-09-08T09:59:25.0327345Z Considered "C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\EntityFramework.winmd", but it didn't exist.
2021-09-08T09:59:25.0329704Z Considered "C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\EntityFramework.dll", but it didn't exist.
2021-09-08T09:59:25.0331000Z Considered "C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\EntityFramework.exe", but it didn't exist.
2021-09-08T09:59:25.0332550Z For SearchPath "{AssemblyFoldersFromConfig:C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\MSBuild\Current\Bin\AssemblyFolders.config,v4.6.1}".
2021-09-08T09:59:25.0333890Z Considered "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\MSBuild\Current\Bin\EntityFramework.winmd", but it didn't exist.
2021-09-08T09:59:25.0334975Z Considered "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\MSBuild\Current\Bin\EntityFramework.dll", but it didn't exist.
2021-09-08T09:59:25.0336185Z Considered "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\MSBuild\Current\Bin\EntityFramework.exe", but it didn't exist.
2021-09-08T09:59:25.0337230Z Considered "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\IDE\Extensions\Microsoft\SqlDb\EntityFramework.winmd", but it didn't exist.
2021-09-08T09:59:25.0338741Z Considered "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\IDE\Extensions\Microsoft\SqlDb\EntityFramework.dll", but it didn't exist.
2021-09-08T09:59:25.0339871Z Considered "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\IDE\Extensions\Microsoft\SqlDb\EntityFramework.exe", but it didn't exist.
2021-09-08T09:59:25.0341008Z Considered "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\IDE\PublicAssemblies\EntityFramework.winmd", but it didn't exist.
2021-09-08T09:59:25.0342446Z Considered "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\IDE\PublicAssemblies\EntityFramework.dll", but it didn't exist.
2021-09-08T09:59:25.0343716Z Considered "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\IDE\PublicAssemblies\EntityFramework.exe", but it didn't exist.
2021-09-08T09:59:25.0344976Z Considered "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\IDE\ReferenceAssemblies\v4.5\EntityFramework.winmd", but it didn't exist.
2021-09-08T09:59:25.0346011Z Considered "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\IDE\ReferenceAssemblies\v4.5\EntityFramework.dll", but it didn't exist.
2021-09-08T09:59:25.0347336Z Considered "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\IDE\ReferenceAssemblies\v4.5\EntityFramework.exe", but it didn't exist.
2021-09-08T09:59:25.0348385Z Considered "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VSSDK\VisualStudioIntegration\Common\Assemblies\v4.0\EntityFramework.winmd", but it didn't exist.
2021-09-08T09:59:25.0349711Z Considered "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VSSDK\VisualStudioIntegration\Common\Assemblies\v4.0\EntityFramework.dll", but it didn't exist.
2021-09-08T09:59:25.0350959Z Considered "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VSSDK\VisualStudioIntegration\Common\Assemblies\v4.0\EntityFramework.exe", but it didn't exist.
2021-09-08T09:59:25.0352430Z Considered "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\IDE\PublicAssemblies\EntityFramework.winmd", but it didn't exist.
2021-09-08T09:59:25.0353536Z Considered "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\IDE\PublicAssemblies\EntityFramework.dll", but it didn't exist.
2021-09-08T09:59:25.0354501Z Considered "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\IDE\PublicAssemblies\EntityFramework.exe", but it didn't exist.
2021-09-08T09:59:25.0355937Z Considered "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\IDE\ReferenceAssemblies\v4.5\EntityFramework.winmd", but it didn't exist.
2021-09-08T09:59:25.0357043Z Considered "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\IDE\ReferenceAssemblies\v4.5\EntityFramework.dll", but it didn't exist.
2021-09-08T09:59:25.0358358Z Considered "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\IDE\ReferenceAssemblies\v4.5\EntityFramework.exe", but it didn't exist.
2021-09-08T09:59:25.0359726Z Considered "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\IDE\ReferenceAssemblies\v4.0\EntityFramework.winmd", but it didn't exist.
2021-09-08T09:59:25.0360920Z Considered "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\IDE\ReferenceAssemblies\v4.0\EntityFramework.dll", but it didn't exist.
2021-09-08T09:59:25.0362581Z Considered "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\IDE\ReferenceAssemblies\v4.0\EntityFramework.exe", but it didn't exist.
2021-09-08T09:59:25.0364118Z Considered "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\IDE\ReferenceAssemblies\v4.0\EntityFramework.winmd", but it didn't exist.
2021-09-08T09:59:25.0365506Z Considered "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\IDE\ReferenceAssemblies\v4.0\EntityFramework.dll", but it didn't exist.
2021-09-08T09:59:25.0366461Z Considered "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\IDE\ReferenceAssemblies\v4.0\EntityFramework.exe", but it didn't exist.
2021-09-08T09:59:25.0367645Z Considered "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\IDE\ReferenceAssemblies\v2.0\EntityFramework.winmd", but it didn't exist.
2021-09-08T09:59:25.0368749Z Considered "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\IDE\ReferenceAssemblies\v2.0\EntityFramework.dll", but it didn't exist.
2021-09-08T09:59:25.0370328Z Considered "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\IDE\ReferenceAssemblies\v2.0\EntityFramework.exe", but it didn't exist.
2021-09-08T09:59:25.0371751Z Considered "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VSSDK\VisualStudioIntegration\Common\Assemblies\v2.0\EntityFramework.winmd", but it didn't exist.
2021-09-08T09:59:25.0373197Z Considered "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VSSDK\VisualStudioIntegration\Common\Assemblies\v2.0\EntityFramework.dll", but it didn't exist.
2021-09-08T09:59:25.0374668Z Considered "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VSSDK\VisualStudioIntegration\Common\Assemblies\v2.0\EntityFramework.exe", but it didn't exist.
2021-09-08T09:59:25.0375585Z Considered "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\IDE\ReferenceAssemblies\v2.0\EntityFramework.winmd", but it didn't exist.
2021-09-08T09:59:25.0376751Z Considered "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\IDE\ReferenceAssemblies\v2.0\EntityFramework.dll", but it didn't exist.
2021-09-08T09:59:25.0377919Z Considered "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\IDE\ReferenceAssemblies\v2.0\EntityFramework.exe", but it didn't exist.
2021-09-08T09:59:25.0378757Z For SearchPath "{Registry:Software\Microsoft\.NETFramework,v4.6.1,AssemblyFoldersEx}".
2021-09-08T09:59:25.0379755Z Considered AssemblyFoldersEx locations.
2021-09-08T09:59:25.0380118Z For SearchPath "{AssemblyFolders}".
2021-09-08T09:59:25.0380669Z Considered "C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\v3.0\EntityFramework.winmd", but it didn't exist.
2021-09-08T09:59:25.0381945Z Considered "C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\v3.0\EntityFramework.dll", but it didn't exist.
2021-09-08T09:59:25.0382984Z Considered "C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\v3.0\EntityFramework.exe", but it didn't exist.
2021-09-08T09:59:25.0384254Z Considered "C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\v3.5\EntityFramework.winmd", but it didn't exist.
2021-09-08T09:59:25.0385219Z Considered "C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\v3.5\EntityFramework.dll", but it didn't exist.
2021-09-08T09:59:25.0386357Z Considered "C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\v3.5\EntityFramework.exe", but it didn't exist.
2021-09-08T09:59:25.0387438Z Considered "C:\Program Files\IIS\Microsoft Web Deploy V3\EntityFramework.winmd", but it didn't exist.
2021-09-08T09:59:25.0388370Z Considered "C:\Program Files\IIS\Microsoft Web Deploy V3\EntityFramework.dll", but it didn't exist.
2021-09-08T09:59:25.0389534Z Considered "C:\Program Files\IIS\Microsoft Web Deploy V3\EntityFramework.exe", but it didn't exist.
2021-09-08T09:59:25.0390627Z Considered "C:\Program Files (x86)\Microsoft SQL Server\130\SDK\Assemblies\EntityFramework.winmd", but it didn't exist.
2021-09-08T09:59:25.0391822Z Considered "C:\Program Files (x86)\Microsoft SQL Server\130\SDK\Assemblies\EntityFramework.dll", but it didn't exist.
2021-09-08T09:59:25.0393042Z Considered "C:\Program Files (x86)\Microsoft SQL Server\130\SDK\Assemblies\EntityFramework.exe", but it didn't exist.
2021-09-08T09:59:25.0394137Z Considered "C:\Program Files (x86)\WiX Toolset v3.11\SDK\EntityFramework.winmd", but it didn't exist.
2021-09-08T09:59:25.0395074Z Considered "C:\Program Files (x86)\WiX Toolset v3.11\SDK\EntityFramework.dll", but it didn't exist.
2021-09-08T09:59:25.0395903Z Considered "C:\Program Files (x86)\WiX Toolset v3.11\SDK\EntityFramework.exe", but it didn't exist.
2021-09-08T09:59:25.0396662Z For SearchPath "{GAC}".
2021-09-08T09:59:25.0397574Z Considered "EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL", which was not found in the GAC.
2021-09-08T09:59:25.0398536Z For SearchPath "{RawFileName}".
2021-09-08T09:59:25.0399682Z Considered treating "EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL" as a file name, but it didn't exist.
2021-09-08T09:59:25.0400706Z For SearchPath "bin\Release\".
2021-09-08T09:59:25.0401283Z Considered "bin\Release\EntityFramework.winmd", but it didn't exist.
2021-09-08T09:59:25.0402284Z Considered "bin\Release\EntityFramework.dll", but it didn't exist.
2021-09-08T09:59:25.0403161Z Considered "bin\Release\EntityFramework.exe", but it didn't exist.
我比較不能理解的地方是,在我自己的電腦用 MSBuild 是可以成功建置的,但是在 Azure Pipelines 的 Hosted Agent 用 MSBuild 就是找不到編譯所需的組件(Assembly)!
解決方法
我經常說:「寫 Code 需要靈感,解 Bug 需要創意」,沒靈感的時候還可以上網抄點 Code,但沒創意你就抓不到這種詭異的 Bug 了!
我最後的解決方法,還是靠眼睛看 Log,搭配創意的大腦思考每一段內容的蛛絲馬跡,最後被我找到這個線索:
Considered "D:\a\1\packages\EntityFramework.6.2.0\lib\net45\EntityFramework.dll", but it didn't exist.
看出來了嗎?還沒?我們再看細一點:
Considered "D:\a\1\packages\..."
我突然恍然大悟,因為 Azure Pipelines 預設的 Source 路徑 (Build.SourcesDirectory
) 是在 D:\a\1\s
目錄下,當我在專案根目錄執行 nuget restore
的時候,照理說 NuGet 的 packages
應是在 D:\a\1\s\packages
目錄才對,怎麼會變成 D:\a\1\packages
目錄呢?
最後我才想到可能是 *.csproj
裡面參考的組件路徑有誤,打開來一看,發現組件參考的 HintPath
路徑真的有錯,當我批次調整錯誤的路徑之後,專案就可以順利的在 CI 自動建置完成了! 😃
問題主因
其實客戶的專案檔原本是好的,但是我們在合併不同專案的時候,有將幾個專案移動到上一層目錄,但是當下並沒有意識到 *.csproj
也要一併修改組件參考的相對路徑。由於 .NET Framework 大部分的組件參考都是相對於 packages
這個 NuGet 套件快取目錄的路徑,當我的專案往上移動一層時,專案檔中的路徑也要一併修改才行,這是我沒有注意到的地方! 🔥
這個問題最終未解的疑惑,就是不知道為什麼在我的電腦可以用 Visual Studio 2019 與 MSBuild 成功建置呢?是不是在其他電腦才不行?是否 MSBuild 的版本不同造成的差異?還是 Visual Studio 2019 版本不同造成的?這個問題等我下次遇到相同問題時再來研究了!
批次重裝所有 NuGet 套件
感謝 Poy Chang 的技術交流中心 分享以下 PowerShell 指令,這個命令可以在 Visual Studio 2019 的 Package Manager Console 底下執行,他會全自動找出所有專案的所有已安裝的 NuGet 套件,並且自動全部重新安裝! 👍
Get-Project -All | % { Get-Package -ProjectName $_.ProjectName | % { Update-Package $_.Id -Reinstall -ProjectName $_.ProjectName -IgnoreDependencies } }
在重新安裝完之後,所有的問題都會自動迎刃而解!
相關連結