Repository navigation
Fix pinned Store apps: duplicates in Recent and search, blank icon after an update - #2575
Open
emilioheredia-source wants to merge 5 commits into
Open
emilioheredia-source wants to merge 5 commits into
emilioheredia-source wants to merge 5 commits into
Conversation
With a shortcut to a Store app in the Start Menu (for example a program pinned to the Classic menu, which lives in the Start Menu root), the Apps folder lists that shortcut in place of the app. Creating the app's item from its AppUserModelID then gives an item with the shortcut's properties: PKEY_MetroAppLauncher=0, no package, and the shortcut named in System.AppUserModel.BestShortcut. An app without a shortcut reports PKEY_MetroAppLauncher=2 and its package, as expected. RefreshItemInfo took such an item for a desktop program: not a link, not a Metro app, so it dropped the appid. In the Recent Programs list this showed as: - a blank page instead of the app's icon, because the icon came from the shortcut, which has no icon of its own; - the app listed in Recent although it is pinned, because for apps the duplicate check compares appids and this one was empty. Seen with Microsoft To Do and Microsoft Store pinned; Quick Assist, not pinned, was fine. Now such an item is resolved through its shortcut to the app, the same way RefreshItemInfo already resolves a link to a Store app: the item and property store become the shortcut's target, if that target has the same appid and is a Metro app. The appid, package and Metro icon then come out right, and the existing duplicate check works.
Searching for a Store app that has a shortcut in the Start Menu (for example one pinned to the Classic menu) listed it twice under Programs: once from the Start Menu folder and once from the Apps folder. GetSearchResults drops a program as a duplicate when its name and appid match one already found, comparing names with wcscmp. Names from the folders are stored uppercase (CollectSearchItems), and so are Metro link names (AddSearchItem), but on Windows 10 and later the apps from GetMetroLinks were added with their display name as it is. So "MICROSOFT TO DO" from the shortcut never matched "Microsoft To Do" from the Apps folder, although both have the same appid (checked with the search log). Store these names uppercase too. The name is only used for matching, which ignores case, and for finding duplicates; the results show the item's own display name, so nothing visible changes except that the duplicate is gone.
…d copy A shortcut to a Store app stores a snapshot of the app's item: the full package name, which includes the version, the install folder and the logo name. Open-Shell resolves such a shortcut to that item and read the package from it. After the app updates itself, that package no longer exists, so: - LoadMetroIcon could not open the package's resources, and the item showed a blank tile. Seen with Microsoft Store pinned to the Classic menu the morning after it updated from 22608.1401.4.0 to 1401.5.0; the shortcut still named 1401.4.0. - the item's package path pointed to a folder that is gone. The Recent Programs list drops an app whose package path does not exist. GetPackageFullName had the same weakness from the other side: it looked the appid up in the Apps folder, and with a shortcut to the app in the Start Menu that item is the shortcut, which has no package at all. The appid (package family name!app name) does not change with updates. Now GetPackageFullName asks Windows for the package of that family installed now (GetPackagesByPackageFamily), and takes the main package, since a family can also list a bundle and resource packages. The old lookup stays as the fallback. LoadMetroIcon and the package path use it, and the saved values only when that finds nothing. The package name is part of the icon cache key now, so a new version of an app shows its new icon. The package functions are loaded with GetProcAddress, as the DLL still loads on Windows 7. CanUninstallMetroApp reads the package path through the Apps folder in the same way; not changed here.
…m has none The previous commit made LoadMetroIcon open the package installed now, but the pinned Microsoft Store still showed a blank page. A diagnostic build logged why: the item came from the data cache already marked as a Metro app, so only its icon was refreshed, and for that RefreshItemInfo looks the appid up in the Apps folder. With a shortcut to the app in the Start Menu, that item is the Apps folder's stand-in for the shortcut, which has no package and no logo name (PKEY_MetroIcon). LoadMetroIcon gave up, and the fallback shell icon of the shortcut is the blank page the taskbar shows too. To Do, Terminal and Teams hid the same failure, because the shell icon of their shortcuts is still good. Now the logo name comes from the item only when the item names the package installed now. For a stand-in, or a snapshot of another version, it comes from AppxManifest.xml of the installed package (Square44x44Logo, or SmallLogo in Windows 8 manifests), read with the Appx manifest reader. That is also right when an update renames the logo. Checked on the real machine with the diagnostic build: all 5 pinned Store apps (Store, To Do, Terminal, Teams, Outlook) loaded their icon from the package, none left to the fallback. Reading the Store's manifest took about 30 ms, once per session.
GetInstalledPackageFullName and GetAppLogoName each did several things in 30-40 lines: splitting the appid, asking Windows for the family's packages, picking the main one; opening the manifest, finding the app, reading its logo. Each step is now its own function (SplitAppId, IsMainPackage, ReadManifestApplications, GetManifestLogo), and the appid is split in one place instead of two. The comments say what each returns when it finds nothing. No change in behaviour: the functions, compiled on their own from this file, return the same packages, folders and logo names as before for Microsoft Store, To Do, Terminal and Teams, and nothing for an unknown package, a desktop program, or an unknown app in a known package.
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Pinning a Store app puts a shortcut to it in the Start Menu folder. With that shortcut, the app
showed up twice in Recent Programs (with a blank icon) and twice in search, and its icon became a
blank page after the app updated itself. Five commits, each with the details in its message:
app in the Start Menu, the Apps folder item for the appid is the shortcut's stand-in:
PKEY_MetroAppLauncher=0, no package, the shortcut inSystem.AppUserModel.BestShortcut.RefreshItemInfotook it for a desktop program and dropped the appid, so the pinned-vs-recentduplicate check (which compares appids) missed it. Now such an item is resolved through its
shortcut to the app, the same way a link to a Store app already is.
are stored uppercase, but the Windows 10+ apps from
GetMetroLinkskept their display name, so"MICROSOFT TO DO" never matched "Microsoft To Do". They are stored uppercase too. The name is
only used for matching, so nothing visible changes except that the duplicate is gone.
keeps the full package name from when it was made, which includes the version. After an update
InitializeForPackagefails with0x80070490.GetPackageFullNamenow asks for the package ofthe appid's family installed now (
GetPackagesByPackageFamily, main package only), andLoadMetroIconand the package path use it. The package name is part of the icon cache key, soa new version's icon replaces the old one.
from the data cache gets its icon through the Apps folder, which gives the stand-in with no logo
name. When the item has no logo name, or names another version, the name is read from the
installed package's
AppxManifest.xml(Square44x44Logo, orSmallLogoin Windows 8manifests).
them on their own and comparing their results for four installed apps and three edge cases.
The package functions are loaded with
GetProcAddress, since the DLL still loads on Windows 7.Tested on Windows 11 26H2 (26300), with Microsoft Store (updated from 22608.1401.4.0 to
1401.5.0 while pinned), Microsoft To Do, Terminal, Teams and Outlook pinned:
correctly, and searching "to do" listed Microsoft To Do once.
along with my other changes, not on this branch alone.
package, none from the fallback. Reading the Store's manifest took about 30 ms, once per session.
(Measured on my daily build too.)
left all five commits unchanged, and since then I've used it every day for two weeks in my
build on that master.
Not changed:
CanUninstallMetroAppreads the package path through the Apps folder in the sameway, so Uninstall may be missing for a pinned Store app. I haven't seen that on screen yet.