dotnet 9 WPF 專案禁用 IncludePackageReferencesDuringMarkupCompilation 導致原始碼包 XAML 構建失敗

lindexi發表於2024-11-20

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 將記錄錯誤的相對檔案路徑,進而導致構建失敗。最簡單的復現方式如下:

  1. 建立兩個 wpf 專案,其中一個為 WPF 庫專案,一個為 WPF 應用專案
  2. 在 WPF 庫專案裡面新增名為 MyUserControl 的使用者控制元件
  3. 在 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>

以上程式碼放在 githubgitee 上,可以使用如下命令列拉取程式碼。我整個程式碼倉庫比較龐大,使用以下命令列可以進行部分拉取,拉取速度比較快

先建立一個空資料夾,接著使用命令列 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

更多技術部落格,請參閱 部落格導航

相關文章