Skip to content

Fix workload advertising manifest extraction with WiX v4+ built MSIs - #55576

Open
marcpopMSFT with Copilot wants to merge 2 commits into
mainfrom
copilot/netsdke2e-fix-path-issue
Open

Fix workload advertising manifest extraction with WiX v4+ built MSIs#55576
marcpopMSFT with Copilot wants to merge 2 commits into
mainfrom
copilot/netsdke2e-fix-path-issue

Conversation

Copilot AI commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

On MSI-based installs, dotnet workload install fails to refresh the microsoft.net.workloads advertising manifest and silently falls back to stale manifests:

Failed to update the advertising manifest microsoft.net.workloads: Could not find a part of the path 'C:\Users...\AppData\Local\Temp\0nwvv1w2.pwu\msi\dotnet\sdk-manifests'.

Root cause

Workload set packages don't ship a data\extractedManifest folder (manifest MSI packages do), so WindowsMsiManifestInstaller.ExtractManifestAsync falls back to an administrative install — ACTION=ADMIN TARGETDIR=<tmp>\msi — and then reads a hardcoded <tmp>\msi\dotnet\sdk-manifests.

Workload MSI generation moved from WiX v3 to WiX v5, which changed the MSI Directory table and therefore the admin-image layout:

Directory table Admin image path
WiX v3 ProgramFiles64Folder | TARGETDIR | . <tmp>\msi\dotnet\sdk-manifests\...
WiX v5 ProgramFiles6432Folder | ProgramFiles64Folder | .
ProgramFiles64Folder | TARGETDIR | PFiles64
<tmp>\msi\PFiles64\dotnet\sdk-manifests\...

(Confirmed by exporting the Directory table from the shipped preview.6 and preview.7 workload MSIs.) During an administrative install directories are resolved from TARGETDIR using DefaultDir, so the v3 . collapsed away while v5 adds a PFiles64 level. The hardcoded path then throws DirectoryNotFoundException. Zip/tar installs are unaffected — they never touch an MSI.

Changes

  • WindowsMsiManifestInstaller: new FindExtractedManifestFolder helper locates sdk-manifests by name under the admin-install target rather than assuming a fixed depth, so both layouts work (and PFiles vs PFiles64 across architectures). The existing "descend two single-child levels" behavior is unchanged.
  • Error surface: when the folder can't be located, the existing ExpectedSingleManifest GracefulException is raised instead of an unhandled DirectoryNotFoundException.
  • Tests: cover the WiX v3 layout, the WiX v4+ layout, and the missing/not-found cases.
-var manifestsFolder = Path.Combine(msiExtractionPath, "dotnet", "sdk-manifests");
-
-string? manifestFolder = null;
-string? manifestsFeatureBandFolder = Directory.GetDirectories(manifestsFolder).SingleOrDefault();
-if (manifestsFeatureBandFolder != null)
-{
-    manifestFolder = Directory.GetDirectories(manifestsFeatureBandFolder).SingleOrDefault();
-}
+string? manifestFolder = FindExtractedManifestFolder(msiExtractionPath);

Notes for reviewers

  • The changed source file and its test file are Windows-only (Compile Remove elsewhere), so they compile and run on Windows CI only.
  • A complementary fix in arcade — having WorkloadSetMsi emit data\extractedManifest like WorkloadManifestMsi does — would remove the admin-install dependency entirely, but is out of scope for this repo.

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
3 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

Co-authored-by: marcpopMSFT <12663534+marcpopMSFT@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix advertising manifest update issue for .NET 11.0.100-preview.7.26379.122 Fix workload advertising manifest extraction with WiX v4+ built MSIs Aug 3, 2026
Copilot AI requested a review from marcpopMSFT August 3, 2026 17:43

@joeloff joeloff left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This is fine. WiX4 introduced a new StandardDirectory that is used to eliminate authoring custom conditionals to select the appropriate ProgramFiles folder. This adds an additional entry in the directory table which is what the SDK is hitting. Since we have a mix of both v3 and v4+ built installers for workloads, we should take this fix

@marcpopMSFT
marcpopMSFT marked this pull request as ready for review August 4, 2026 23:48
Copilot AI review requested due to automatic review settings August 4, 2026 23:48
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).
2 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Fixes dotnet workload install advertising-manifest refresh on Windows MSI-based installs when the admin-image layout differs (WiX v4+/v5 adding a PFiles* directory level), avoiding a hardcoded msi\dotnet\sdk-manifests assumption.

Changes:

  • Updates WindowsMsiManifestInstaller.ExtractManifestAsync to locate the extracted sdk-manifests folder via a new helper instead of a fixed path.
  • Adds FindExtractedManifestFolder to search for the admin-image manifest layout across WiX variants and return null when not found.
  • Adds Windows-only tests covering WiX v3 layout, WiX v4+ layout, and missing-manifest cases.

Reviewed changes

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

File Description
src/Cli/dotnet/Commands/Workload/Install/WindowsMsiManifestInstaller.cs Adds helper to locate sdk-manifests under MSI admin-image output and uses it during extraction.
test/dotnet.Tests/CommandTests/Workload/Install/GivenAWindowsMsiManifestInstaller.cs Adds unit tests validating the helper against WiX v3 vs v4+ layouts and not-found behavior.

Comment on lines +172 to +176
string? manifestsFolder = Directory.EnumerateDirectories(msiExtractionPath, "sdk-manifests", SearchOption.AllDirectories).FirstOrDefault();
if (manifestsFolder == null)
{
return null;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

4 participants