Skip to content

Refresh the WinGet COM installed index before listing local packages - #5585

Merged
Gabriel Dufresne (GabrielDuf) merged 1 commit into
mainfrom
fix/winget-com-stale-msix-versions
Oct 23, 2026
Merged

Gabriel Dufresne (GabrielDuf) merged 1 commit into
mainfrom
fix/winget-com-stale-msix-versions

Conversation

@GabrielDuf

@GabrielDuf Gabriel Dufresne (GabrielDuf) commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

Why

With the default native WinGet backend (COM API), an MSIX package that was just updated keeps showing its old version and keeps being offered as an update. Running that update again then fails with 0x8A15002B ("No newer package versions are available"). This affects Oh My Posh, NanaZip, Command Palette extensions and other MSIX packages, whether UniGetUI or the Microsoft Store did the update. Packages installed with a classic installer are unaffected, and so are the WinGet CLI and Pinget.

The stale data comes from the WinGet COM server, which is why the template box above is left unchecked. The server keeps a process-wide cache of installed packages (CachedInstalledIndex in winget-cli's PredefinedInstalledSourceFactory.cpp, identical in v1.29.280 and in the 1.12.350 interop this repo uses). It rebuilds that cache only when:

  • an ARP (Uninstall) registry key changes, or
  • PackageCatalog.PackageStatusChanged fires.

An MSIX install, upgrade or removal done outside the server does neither. That covers winget.exe, which UniGetUI runs for operations, and Store auto-updates. So the COM listing stays stale for as long as the server process lives. Any long-lived COM client keeps the server alive: UniGetUI itself, or PowerToys Command Palette. That's why Reset WinGet (which kills WindowsPackageManagerServer.exe) helped only once. The CLI and Pinget are fine because each call is a fresh process.

The cache is used only for the default InstalledScope, and the COM API offers no way to force a refresh (InstalledForceCacheUpdate is CLI-only). No upstream fix is expected, so UniGetUI has to work around it.

What changed (NativeWinGetHelper.cs)

Before each local package enumeration, GetLocalWinGetPackages now sets and immediately deletes a value on HKCU\Software\Microsoft\Windows\CurrentVersion\Uninstall. The server's recursive ARP registry watcher sees the change and rebuilds the index on the next connect. This is the same refresh a classic install already triggers.

  • It writes a value on the key itself, not a subkey, so no Apps & Features entry can appear, even if the delete is interrupted.
  • If the key is missing or the write fails, it logs the failure and carries on.
  • One call site covers updates made by UniGetUI, Store auto-updates and manual reloads. The CLI and Pinget paths don't need it.

Rejected alternatives:

  • Killing the COM server: this breaks other COM clients and in-flight calls.
  • Querying user and machine scope separately: the two don't add up to the default list (machine scope adds provisioned packages).
  • Reading MSIX versions ourselves: we would have to recompute update availability and correlate ids with WinGet.

Verification

  • Repro: a scratch console app kept one COM PackageManager alive while a throwaway loose-file MSIX was registered, updated (1.0.0.0 → 1.0.1.0) and removed.
    • Without the write, the COM listing missed all three changes. It still reported 1.0.0.0 after the update and still listed the package after removal.
    • With the exact write the fix uses, the next enumeration was correct every time.
    • Extra cost: about 100–150 ms per enumeration, which is already cached for 15 s.
  • Build: no new warnings.
  • Formatting: dotnet format whitespace and dotnet format style both exit 0 with --verify-no-changes.
  • Tests: the full UniGetUI.PackageEngine.Tests project passes.

Closes #5188

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.

🔵 Needs a closer look

The workaround relies on cross-process registry notifications and still needs validation against a real MSIX upgrade in the running Windows app.

No open issues 🎉

What changed in this PR

This PR addresses stale MSIX versions in UniGetUI’s native WinGet backend by triggering an installed-index refresh before local package enumeration.

Changes:

  • Sets and deletes a temporary value on the per-user Uninstall registry key to notify the WinGet COM server.
  • Logs missing-key or write failures and continues enumeration.
  • Leaves CLI, Pinget, and UniGetUI’s separate 15-second cache unchanged.
File Description
src/​UniGetUI.PackageEngine.Managers.WinGet/​ClientHelpers/​NativeWinGetHelper.cs Adds best-effort registry-based cache invalidation before native local package queries.

Review effort: Balanced

@randy-but-a-ro randy-but-a-ro Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🤖 Pull request was approved automatically: the AI review is complete and all its review threads are resolved. 🎉

Integration Details
{
	"deliveryId": "e12cfdc0-cee9-11f1-9196-49eebeebbfd3",
	"headSha": "327657ca10fb4ba25aaf3b3faccb9c59550e9cef",
	"reviewer": "copilot-pull-request-reviewer[bot]"
}

@GabrielDuf
Gabriel Dufresne (GabrielDuf) merged commit 7a42c58 into main Oct 23, 2026
6 checks passed
@GabrielDuf
Gabriel Dufresne (GabrielDuf) deleted the fix/winget-com-stale-msix-versions branch October 23, 2026 14:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] Winget COM API doesn’t update the version after successful package udpate

2 participants