Skip to content

MRT ResourceManager default constructor doesn't find [modulename].pri for sparse-packaged apps #6375

@yeelam-gordon

Description

@yeelam-gordon

Description

Sparse-packaged apps (apps with package identity registered via AddPackageByUriAsync) that use a custom ProjectPriFileName (e.g., AssemblyName.pri) cannot load resources through the default ResourceManager() constructor.

Related: microsoft/microsoft-ui-xaml#10856

Why This Matters

Unpackaged apps that need package-identity-only APIs (e.g., Windows AI APIs) must use sparse app registration (AddPackageByUriAsync) to acquire identity. When multiple such apps share the same output directory, each needs its own module-specific PRI (via ProjectPriFileName) to avoid resource conflicts — but this bug prevents sparse-packaged apps from discovering any PRI file other than resources.pri.

Root Cause

In dev/MRTCore/mrt/Microsoft.Windows.ApplicationModel.Resources/src/Helper.cpp, GetDefaultPriFile() calls GetDefaultPriFileForCurrentPackage() first. For sparse apps this fails (resources aren't deployed through the package system), but the error is not APPMODEL_ERROR_NO_PACKAGE because sparse apps do have package identity.

This causes isPackaged = true, so GetDefaultPriFileForCurentModule(true, ...) passes "resources.pri" to MrmGetFilePathFromName ΓÇö which only searches for that exact filename. The [modulename].pri fallback (triggered by passing nullptr) is never reached.

GetDefaultPriFile
+-- GetDefaultPriFileForCurrentPackage -> FAILS (sparse app, not real package)
+-- isPackaged = true (has identity, not APPMODEL_ERROR_NO_PACKAGE)
+-- GetDefaultPriFileForCurentModule(true) -> MrmGetFilePathFromName("resources.pri") -> NOT FOUND
+-- Returns error -- never tries nullptr path which would find [modulename].pri

Affected Scenarios

Deployment Identity resources.pri exists [module].pri exists Result
Fully packaged Yes Yes (via package) N/A Works
Unpackaged No No Yes Works (nullptr path)
Sparse Yes No Yes Broken

Proposed Fix

When GetDefaultPriFileForCurentModule(isPackaged=true) fails for an app with identity, fall back to GetDefaultPriFileForCurentModule(false) which passes nullptr to MrmGetFilePathFromName, triggering the broader search including [modulename].pri.

If the fallback also fails, return the original HRESULT to preserve error behavior for existing callers.

Impact

  • Affects any sparse-packaged app using MRT ResourceManager() default constructor with a custom PRI filename
  • WinUI controls also fail to load localized strings in self-contained sparse app deployments
  • Fix is scoped: only activates for apps with identity where resources.pri was not found

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions