在 WPF 修復 dotnet 6 與原始碼包衝突 這篇部落格裡面和大家介紹透過禁用 IncludePackageReferencesDuringMarkupCompilation 解決原始碼衝突問題
以下是在 dotnet 6 裡的構建失敗資訊
C:\Program Files\dotnet\sdk\6.0.101\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.Sdk.DefaultItems.Shared.targets(190,5): error NETSDK1022: 包含了重複的“Compile”項。.NET SDK 預設包含你專案目錄中的“Compile”項。可從專案檔案中刪除這些項;如果希望將其顯式包含在專案檔案中,可將“EnableDefaultCompileItems”屬性設定為“false”。有關詳細資訊,請參閱 https://aka.ms/sdkimplicititems。重複項為:
透過禁用 IncludePackageReferencesDuringMarkupCompilation 即可解決,程式碼如下
<IncludePackageReferencesDuringMarkupCompilation>False</IncludePackageReferencesDuringMarkupCompilation>
更改之後的 csproj 程式碼如下
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net6.0-windows</TargetFramework>
<UseWPF>true</UseWPF>
<IncludePackageReferencesDuringMarkupCompilation>False</IncludePackageReferencesDuringMarkupCompilation>
</PropertyGroup>
</Project>
依然是上述程式碼不變,升級到 dotnet 9 的 SDK 之後,將會讓程式碼構建不透過。假定原始碼包裡面包含了 MyControl.xaml 檔案,那麼構建過程提示錯誤內容大概如下
MyControl.g.cs(62,18): error CS1504: 無法開啟原始檔“MyControl.xaml”-- 無法找到檔案
進入到 obj 資料夾下,去看 MyControl.g.cs 檔案,可以看到開始的 #pragma checksum
記錄的就是錯誤的相對路徑
#pragma checksum "MyControl.xaml" "{ff1916ec-aa5e-4d10-97f7-6f4963933460}" "196544C162DD55A903399A4024C5999A1B6017EB"
預期的情況下,此時的記錄應該是一個正確的相對路徑或絕對路徑,如下面程式碼所示才是正確的
#pragma checksum "..\..\..\..\..\..\..\..\..\..\..\Users\lindexi\.nuget\packages\lindexi.package.wpf.source\1.0.0\src\View\MyControl.xaml" "{ff1916ec-aa5e-4d10-97f7-6f4963933460}" "196544C162DD55A903399A4024C5999A1B6017EB"
解決方法只有是開啟 IncludePackageReferencesDuringMarkupCompilation 功能,即只需註釋掉 <IncludePackageReferencesDuringMarkupCompilation>False</IncludePackageReferencesDuringMarkupCompilation>
即可
當然了,註釋掉 IncludePackageReferencesDuringMarkupCompilation 的禁用,則又會出現原始碼相容問題。不過現在是 dotnet 9 了,是時候更新原始碼包啦
<IncludePackageReferencesDuringMarkupCompilation Condition="$([MSBuild]::VersionGreaterThanOrEquals($(NETCoreSdkVersion), 9.0))">True</IncludePackageReferencesDuringMarkupCompilation>
以上程式碼為常寫的判斷程式碼,但在使用以上程式碼之前,還請確保原始碼包已經更新
禁用 IncludePackageReferencesDuringMarkupCompilation 導致構建時 #pragma checksum
記錄錯誤的路徑,這個問題不單只是在引用原始碼包的時候能夠出現,也能夠在跨專案引用 xaml 時復現
禁用 IncludePackageReferencesDuringMarkupCompilation 功能,將會導致在跨專案引用 xaml 檔案,將 xaml 檔案作為連結方式新增時,構建過程中出現 error CS1504 錯誤
禁用 IncludePackageReferencesDuringMarkupCompilation 功能之後,從 xaml 生成的 g.cs 檔案裡的 #pragma checksum
將記錄錯誤的相對檔案路徑,進而導致構建失敗。最簡單的復現方式如下:
- 建立兩個 wpf 專案,其中一個為 WPF 庫專案,一個為 WPF 應用專案
- 在 WPF 庫專案裡面新增名為 MyUserControl 的使用者控制元件
- 在 WPF 應用專案裡面透過以下程式碼引用 MyUserControl.xaml 和 MyUserControl.xaml.cs 檔案
<ItemGroup>
<Compile Include="..\HalllidanairjelDawearlairnal\MyUserControl.xaml.cs" Link="MyUserControl.xaml.cs" />
<Page Include="..\HalllidanairjelDawearlairnal\MyUserControl.xaml" Link="MyUserControl.xaml">
<Generator>MSBuild:Compile</Generator>
</Page>
</ItemGroup>
如果此時同樣在 WPF 應用專案裡設定禁用 IncludePackageReferencesDuringMarkupCompilation 功能,則構建時將會提示 obj\Debug\net9.0-windows\MyUserControl.g.cs(59,21,59,41): error CS1504: 無法開啟原始檔“MyUserControl.xaml”-- 無法找到檔案
錯誤。以下是設定禁用 IncludePackageReferencesDuringMarkupCompilation 功能的 WPF 應用專案的 csproj 專案檔案的程式碼
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net9.0-windows</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<UseWPF>true</UseWPF>
<IncludePackageReferencesDuringMarkupCompilation>False</IncludePackageReferencesDuringMarkupCompilation>
</PropertyGroup>
<ItemGroup>
<Compile Include="..\HalllidanairjelDawearlairnal\MyUserControl.xaml.cs" Link="MyUserControl.xaml.cs" />
<Page Include="..\HalllidanairjelDawearlairnal\MyUserControl.xaml" Link="MyUserControl.xaml">
<Generator>MSBuild:Compile</Generator>
</Page>
</ItemGroup>
</Project>
以上程式碼放在 github 和 gitee 上,可以使用如下命令列拉取程式碼。我整個程式碼倉庫比較龐大,使用以下命令列可以進行部分拉取,拉取速度比較快
先建立一個空資料夾,接著使用命令列 cd 命令進入此空資料夾,在命令列裡面輸入以下程式碼,即可獲取到本文的程式碼
git init
git remote add origin https://gitee.com/lindexi/lindexi_gd.git
git pull origin ee493914d4ac77e06bf6ac789ad84a0e8452be76
以上使用的是國內的 gitee 的源,如果 gitee 不能訪問,請替換為 github 的源。請在命令列繼續輸入以下程式碼,將 gitee 源換成 github 源進行拉取程式碼。如果依然拉取不到程式碼,可以發郵件向我要程式碼
git remote remove origin
git remote add origin https://github.com/lindexi/lindexi_gd.git
git pull origin ee493914d4ac77e06bf6ac789ad84a0e8452be76
獲取程式碼之後,進入 WPFDemo/TestIncludePackageReferencesDuringMarkupCompilation 資料夾,即可獲取到原始碼
大家可以嘗試拉取專案程式碼跑跑看。 此問題已經和 WPF 官方報告,詳細請看 https://github.com/dotnet/wpf/issues/10093
更多技術部落格,請參閱 部落格導航