Skip to content

[Dynamic Dependencies] WinUI 2 fails to load resources #3242

@dongle-the-gadget

Description

@dongle-the-gadget

Describe the bug

When using Windows App SDK Dynamic Dependencies (MddTryCreatePackageDependency and MddAddPackageDependency), WinUI 2 isn't able to load the appropriate resources.

onecoreuap\base\mrt\runtime\com\dllsrv\mrtresourcemanager.cpp(228)\MrmCoreR.dll!00007FF86B9A2009: (caller: 00007FF869CC9435) ReturnHr(22) tid(c0) 80073B1F ResourceMap Not Found.
Exception thrown at 0x00007FF87DC1E1FC (KernelBase.dll) in XamlIslandsApplication.exe: WinRT originate error - 0x80004005 : 'Cannot locate resource from 'ms-appx://Microsoft.UI.Xaml.2.7/Microsoft.UI.Xaml/Themes/21h1_themeresources.xaml'.'.

Steps to reproduce the bug

Problematic code:

void RegisterPackageDependency(LPCWSTR packageFamilyName, PACKAGE_VERSION minVersion)
{
    MddPackageDependencyProcessorArchitectures arch;
#if defined(_M_X64)
    arch = MddPackageDependencyProcessorArchitectures::X64;
#elif defined(_M_ARM64)
    arch = MddPackageDependencyProcessorArchitectures::Arm64;
#elif defined(_M_IX86)
    arch = MddPackageDependencyProcessorArchitectures::X86;
#endif
    
    PWSTR dependencyId, discardedPfn;
    MDD_PACKAGEDEPENDENCY_CONTEXT discardedContext;
    MddTryCreatePackageDependency(NULL, packageFamilyName, minVersion, arch, MddPackageDependencyLifetimeKind::Process, NULL, MddCreatePackageDependencyOptions::None, &dependencyId);
    // Give a higher rank so that our packages are prioritized over Windows App SDK.
    MddAddPackageDependency(dependencyId, -1, MddAddPackageDependencyOptions::None, &discardedContext, &discardedPfn);
}

MddBootstrapInitialize(::Microsoft::WindowsAppSDK::Release::MajorMinor, ::Microsoft::WindowsAppSDK::Release::VersionTag, PACKAGE_VERSION{});
    
RegisterPackageDependency(L"Microsoft.VCLibs.140.00_8wekyb3d8bbwe", PACKAGE_VERSION{
    .Revision = 0,
    .Build = 30704,
    .Minor = 0,
    .Major = 14
});

RegisterPackageDependency(L"Microsoft.UI.Xaml.2.7_8wekyb3d8bbwe", PACKAGE_VERSION{
    .Revision = 0,
    .Build = 13004,
    .Minor = 2109,
    .Major = 7
});

xamlApp = ::winrt::Microsoft::Toolkit::Win32::UI::XamlHost::XamlApplication({ winrt::Microsoft::UI::Xaml::XamlTypeInfo::XamlControlsXamlMetaDataProvider() });
auto test = winrt::Microsoft::UI::Xaml::Controls::XamlControlsResources{}; // fails here

Project configuration:

  1. Requires Microsoft.UI.Xaml 2.7, Microsoft.WindowsAppSDK and Microsoft.Toolkit.Win32.UI.XamlApplication
  2. Add these lines to a PropertyGroup:
    <BeforeLinkTargets>
      $(BeforeLinkTargets);
      _UnpackagedWin32GenerateAdditionalWinmdManifests;
    </BeforeLinkTargets>
  3. Add these targets
    <Target Name="RemoveWinUI3" BeforeTargets="ResolveAssemblyReferences">
      <ItemGroup>
        <_WinUI3Reference Include="@(Reference)" Condition="'%(Filename)' == 'Microsoft.WinUI' OR ($([System.String]::Copy('%(FullPath)').ToLowerInvariant().Contains('windowsappsdk')) AND %(Filename) == 'Microsoft.UI.Xaml')" />
        <Reference Remove="@(_WinUI3Reference)" />
        <ReferenceCopyLocalPaths Remove="@(ReferenceCopyLocalPaths)" Condition="'%(Filename)' == 'Microsoft.WinUI' OR ($([System.String]::Copy('%(FullPath)').ToLowerInvariant().Contains('windowsappsdk')) AND %(Filename) == 'Microsoft.UI.Xaml')" />
      </ItemGroup>
    </Target>
    <Target Name="_UnpackagedWin32MapWinmdsToManifestFiles" DependsOnTargets="ResolveAssemblyReferences">
      <ItemGroup>
        <!-- For each non-system .winmd file in References, generate a .manifest in IntDir for it. -->
        <_UnpackagedWin32WinmdManifest Include="@(ReferencePath->'$(IntDir)\%(FileName).manifest')" Condition="'%(ReferencePath.IsSystemReference)' != 'true' and '%(ReferencePath.WinMDFile)' == 'true' and '%(ReferencePath.ReferenceSourceTarget)' == 'ResolveAssemblyReference' and '%(ReferencePath.Implementation)' != ''">
          <WinMDPath>%(ReferencePath.FullPath)</WinMDPath>
          <Implementation>%(ReferencePath.Implementation)</Implementation>
        </_UnpackagedWin32WinmdManifest>
        <!-- For each referenced project that _produces_ a winmd, generate a temporary item that maps to
           the winmd, and use that temporary item to generate a .manifest in IntDir for it.
           We don't set Implementation here because it's inherited from the _ResolvedNativeProjectReferencePaths. -->
        <_UnpackagedWin32WinmdProjectReference Condition="'%(_ResolvedNativeProjectReferencePaths.ProjectType)' != 'StaticLibrary'" Include="@(_ResolvedNativeProjectReferencePaths-&gt;WithMetadataValue('FileType','winmd')-&gt;'%(RootDir)%(Directory)%(TargetPath)')" />
        <_UnpackagedWin32WinmdManifest Include="@(_UnpackagedWin32WinmdProjectReference->'$(IntDir)\%(FileName).manifest')">
          <WinMDPath>%(Identity)</WinMDPath>
        </_UnpackagedWin32WinmdManifest>
      </ItemGroup>
    </Target>
    <Target Name="_UnpackagedWin32GenerateAdditionalWinmdManifests" Inputs="@(_UnpackagedWin32WinmdManifest.WinMDPath)" Outputs="@(_UnpackagedWin32WinmdManifest)" DependsOnTargets="_UnpackagedWin32MapWinmdsToManifestFiles">
      <Message Text="Generating manifest for %(_UnpackagedWin32WinmdManifest.WinMDPath)" Importance="High" />
      <!-- This target is batched and a new Exec is spawned for each entry in _UnpackagedWin32WinmdManifest. -->
      <Exec Command="mt.exe -winmd:%(_UnpackagedWin32WinmdManifest.WinMDPath) -dll:%(_UnpackagedWin32WinmdManifest.Implementation) -out:%(_UnpackagedWin32WinmdManifest.Identity) -nologo" />
      <ItemGroup>
        <!-- Emit the generated manifest into the Link inputs. Pass a metadata name that isn't used to wipe all 
            metadata because otherwise VS tries copying the manifest to the output as %(FileName).winmd. -->
        <Manifest Include="@(_UnpackagedWin32WinmdManifest)" KeepMetadata="DoesntExist" />
      </ItemGroup>
    </Target>

Expected behavior

WinUI 2 should be able to find the resources.

Screenshots

No response

NuGet package version

Windows App SDK 1.2.1: 1.2.221116.1

Packaging type

Unpackaged

Windows version

Insider Build (xxxxx)

IDE

Visual Studio 2022-preview

Additional context

Using Windows 11 Dynamic Dependencies (TryCreatePackageDependency and AddPackageDependency) doesn't cause this problem.

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions