Skip to content

Fix sparse-packaged apps unable to discover module-specific PRI files#6376

Merged
yeelam-gordon merged 7 commits intomainfrom
fix/sparse-app-pri-discovery
Apr 9, 2026
Merged

Fix sparse-packaged apps unable to discover module-specific PRI files#6376
yeelam-gordon merged 7 commits intomainfrom
fix/sparse-app-pri-discovery

Conversation

@yeelam-gordon
Copy link
Copy Markdown
Contributor

@yeelam-gordon yeelam-gordon commented Apr 3, 2026

Summary

Fixes sparse-packaged apps (unpackaged + self-contained WinUI3 with identity via AddPackageByUriAsync) failing to locate module-specific PRI files (e.g., MyApp.pri set via ProjectPriFileName).

Why This Matters

Not an regression, it doesn't work from the first day.

While 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. This fix unblocks that scenario - without it, any sparse-packaged app with a custom PRI name fails to load resources.

Problem

GetDefaultPriFile() determines isPackaged=true for sparse apps because they have package identity. This causes GetDefaultPriFileForCurentModule to pass "resources.pri" to MrmGetFilePathFromName, which only searches for that exact filename - skipping the [modulename].pri fallback that unpackaged apps (the one leverage sparse app) receive.

When multiple apps share the same output directory, each needs its own module-specific PRI to avoid conflicts, but sparse apps could only find resources.pri.

Fix

When the packaged "resources.pri" search fails for apps with identity, fall back to the unpackaged discovery path (pass nullptr to MrmGetFilePathFromName) which triggers the broader search including "[modulename].pri" derived from the process executable name.

The fallback is gated on IsResourceNotFound(hr) to ensure only genuine not-found conditions trigger it, avoiding masking real errors (e.g., E_OUTOFMEMORY, E_ACCESSDENIED). If the fallback also fails, the original HRESULT from the "resources.pri" search is returned for backward compatibility so callers checking for specific errors (e.g., ERROR_FILE_NOT_FOUND) are not broken.

Changed file

  • dev/MRTCore/mrt/Microsoft.Windows.ApplicationModel.Resources/src/Helper.cpp

Existing test coverage

  • DefaultResourceManagerWithExePri — validates the nullptr fallback mechanism

  • DefaultResourceManager — validates error behavior when no PRI exists

  • DefaultResourceManagerWithResourcePri — validates the normal packaged path

A full sparse-app integration test requires actual sparse package registration (AddPackageByUriAsync) which is beyond unit test scope.

Validation

  • Builds clean with no warnings

  • /azp run pipeline validation


A microsoft employee must use /azp run to validate using the pipelines below.

WARNING:

Comments made by azure-pipelines bot maybe inaccurate.

Please see pipeline link to verify that the build is being ran.

For status checks on the main branch, please use TransportPackage-Foundation-PR

(https://microsoft.visualstudio.com/ProjectReunion/_build?definitionId=81063&_a=summary)

and run the build against your PR branch with the default parameters.

Sparse-packaged apps have package identity (via AddPackageByUriAsync) but
deploy resources as loose files next to the executable. GetDefaultPriFile()
determines isPackaged=true for these apps (since they have identity), causing
GetDefaultPriFileForCurentModule to pass "resources.pri" to
MrmGetFilePathFromName — which only searches for that exact filename,
skipping the [modulename].pri fallback that unpackaged apps receive.

When the "resources.pri" search fails for apps with identity, fall back to
the unpackaged discovery path (pass nullptr to MrmGetFilePathFromName) which
triggers the broader search including "[modulename].pri" derived via
PathCchRenameExtension from the process executable name.

If the fallback also fails, return the original HRESULT from the
"resources.pri" search so callers that check for specific errors
(e.g., ERROR_FILE_NOT_FOUND) are not broken.

Existing test coverage:
- DefaultResourceManagerWithExePri validates the nullptr fallback mechanism
- DefaultResourceManager validates error behavior when no PRI exists
- DefaultResourceManagerWithResourcePri validates the normal packaged path

A full sparse-app integration test requires actual sparse package
registration (AddPackageByUriAsync) which is beyond unit test scope.

Fixes: microsoft/microsoft-ui-xaml#10856

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@yeelam-gordon
Copy link
Copy Markdown
Contributor Author

/azp run

@yeelam-gordon yeelam-gordon requested a review from Copilot April 3, 2026 05:25
@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 1 pipeline(s).

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates MRTCore’s default PRI discovery logic to support sparse-packaged apps (apps with package identity but deploying PRI files as loose files next to the executable), ensuring module-specific PRI files (e.g., [modulename].pri) can be discovered when resources.pri is not present.

Changes:

  • After a failed packaged-module lookup ("resources.pri"), add a fallback to the unpackaged discovery path (MrmGetFilePathFromName(nullptr, ...)) for apps with identity.
  • Preserve the original HRESULT from the packaged-module lookup when the fallback also fails.

@yeelam-gordon yeelam-gordon requested a review from Copilot April 3, 2026 05:43
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated 1 comment.

@yeelam-gordon yeelam-gordon requested a review from Copilot April 3, 2026 05:50
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated 1 comment.

@yeelam-gordon
Copy link
Copy Markdown
Contributor Author

@copilot review

Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 3, 2026

@copilot review

Reviewed the current state of Helper.cpp. No bugs or concerns in the changed code — the fallback is correctly gated on IsResourceNotFound(hr), the original HRESULT is preserved for backward compatibility when both paths fail, and comments are concise single-line statements.

@yeelam-gordon
Copy link
Copy Markdown
Contributor Author

/azp run

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 1 pipeline(s).

@yeelam-gordon yeelam-gordon requested a review from Scottj1s April 3, 2026 06:01
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated 1 comment.

@yeelam-gordon yeelam-gordon merged commit d5afea6 into main Apr 9, 2026
53 checks passed
@yeelam-gordon yeelam-gordon deleted the fix/sparse-app-pri-discovery branch April 9, 2026 01:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

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

4 participants