Skip to content

UWP XBF files lose subdirectory paths in resources.pri when UseArtifactsOutput is enabled #53556

@dfederm

Description

@dfederm

Summary

When a UWP project (UseUwp=true) uses the artifacts output layout (UseArtifactsOutput=true), compiled XAML files (XBF) in subdirectories lose their directory prefix when embedded into resources.pri. This causes a runtime XamlParseException with "Cannot locate resource from 'ms-appx:///...'" because the generated code-behind references paths like ms-appx:///Resources/Styles.xaml but the PRI only contains them at the root (e.g., Files/Styles.xbf instead of Files/Resources/Styles.xbf).

Repro

  1. Create a UWP project targeting net10.0-windows10.0.26100.0 with UseUwp=true and UseArtifactsOutput=true
  2. Place a XAML file in a subdirectory, e.g., Resources/Styles.xaml with x:Class="MyApp.Resources.Styles"
  3. Build and run
  4. App crashes at startup with:
Windows.UI.Xaml.Markup.XamlParseException: XAML parsing failed.
WinRT information: Cannot locate resource from 'ms-appx:///Resources/Styles.xaml'.

Analysis

The XAML compiler generates code-behind that loads XAML via the original relative path:

global::System.Uri resourceLocator = new global::System.Uri("ms-appx:///Resources/Styles.xaml");

However, when UseArtifactsOutput=true redirects the intermediate output to artifacts/obj/<project>/debug/, the build step that populates the PRI layout (filtered.layout.resfiles) loses the subdirectory prefix. The XBF files are listed as flat filenames:

Styles.xbf          <-- wrong, should be Resources\Styles.xbf
Templates.xbf       <-- wrong, should be Resources\Templates.xbf
Home.xbf            <-- wrong, should be Views\Home.xbf

Meanwhile, non-generated content like Assets correctly preserves paths:

Assets\StoreLogo.png  <-- correct

The resources.pri dump confirms the mismatch:

<!-- What it generates (wrong): -->
<NamedResource name="Styles.xbf" uri="ms-resource://MyApp/Files/Styles.xbf">

<!-- What it should generate: -->
<NamedResource name="Styles.xbf" uri="ms-resource://MyApp/Files/Resources/Styles.xbf">

Root cause

The _GeneratedXbfFiles items produced by the XAML compiler have full paths under the intermediate output directory (e.g., artifacts/obj/JellyBox/debug/Resources/Styles.xbf). When these items are processed for PRI layout generation, the relative path calculation strips the subdirectory — likely using %(Filename)%(Extension) rather than computing the path relative to $(IntermediateOutputPath).

This does not reproduce without UseArtifactsOutput=true, because the default output layout places intermediate files in a location where the relative path calculation happens to work correctly.

Workaround

Add DisableEmbeddedXbf=true and a target that re-adds the XBF files as Content with correct Link metadata:

<PropertyGroup>
  <DisableEmbeddedXbf>true</DisableEmbeddedXbf>
</PropertyGroup>

<Target Name="FixXbfContentPaths" AfterTargets="MarkupCompilePass2">
  <ItemGroup>
    <Content Include="@(_GeneratedXbfFiles)"
             Link="$([MSBuild]::MakeRelative($(IntermediateOutputPath), %(FullPath)))"
             CopyToOutputDirectory="PreserveNewest" />
  </ItemGroup>
</Target>

Environment

  • .NET SDK: 10.0.x
  • Windows SDK: 10.0.26100.0
  • OS: Windows 11
  • Project properties: UseUwp=true, UseUwpTools=true, UseArtifactsOutput=true

Metadata

Metadata

Labels

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions