Repository navigation
fix: check what is installed again before removing what an uninstall left - #3229
Merged
Merged
Conversation
…left The Left behind card stays until it is dismissed, so an app can be installed again, or another app into one of its folders, before Remove ticked is pressed. The removal checked each folder's location and links again and nothing else, so the install folder, the AppData folder and the settings key of an app installed again since were removed. Each item is now held to the search's rules again, against the uninstall entries Windows holds at that moment: nothing an installed app lives in, inside or around; nothing left by an app of the same name that is installed again; nothing found by a name an installed app answers to. While that list cannot be read whole, only the install folder can go, as in the search. Every item records the app that left it. The link check walked the folder again and read a walk it had not finished as "no link inside": a folder it could not open was skipped, and a Cancel ended the walk early. The walk now reports the folders it could not list, a folder it could not look through whole is neither offered nor removed, and a Cancel during the check stops the removal before that folder. A refusal was said once per folder by matching the start of the sentences already written, which also matched a sibling whose name starts the same way, so its refusal was never shown. Refusals are now kept by the folder's path.
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.
The Left behind card stays on the Uninstaller until it is dismissed, so between finding what an uninstall left and pressing Remove ticked… the app can be installed again, or another app into one of the listed folders. The removal re-checked each folder's location and links and nothing else, so it could send a freshly installed app's folder, its AppData folder and its settings key to the Recycle Bin or delete them. The pending list read back in an administrator session already applied the full rules; the same-session removal now does too.
What changes
LeftoverService.RemoveAsyncreads the uninstall entries Windows holds once per removal, and every folder and key is held to the search's rules again before it goes: refused when an installed app lives in it, inside it or around it (SharedWith), when it was left by an app whose name is registered again, and, for what was found by a name, when an installed app answers to that name (IsShared, by the publisher for a Guess). While that list cannot be read whole, nothing found by a name is removed, as in the search; the install folder came from the app's own entry and is held to the rules that need no name. Each refusal is one sentence on the status line, like the others.LeftoverItem.AppNamerecords which app left each item, set by the search and by the pending list.SafeWalkOptions.Unreadablecollects the folders the walk could not list.MeasureFolderreports whether it listed everything and throws when its token was cancelled, instead of reading an unfinished walk as "no link inside". A folder it could not look through whole is not offered by the search, not removed, and not offered again from the pending list.LeftoverFinder.AddFolderis kept by path. Matching the start of the sentences already written also matched a sibling such asAcmeafterAcme Notes, whose refusal was then never shown.How it was checked
Each new test was run against the code with its rule taken out, and failed for that reason:
RemoveFolder,AFolderAnAppWasInstalledIntoSinceTheSearch_IsNotRemoved,AFolderFoundByItsName_IsNotRemoved_OnceAnInstalledAppAnswersToThatName,APublisherFolder_IsNotRemoved_OnceAnotherAppOfThatPublisherIsInstalled,WhatAnAppInstalledAgainLeft_IsKept_FolderAndKeyAlikeandWhileTheUninstallListCannotBeReadWhole_OnlyTheInstallFolderCanGofailed. Taking out only the name-registered-again rule, only the key's re-check, or only the incomplete-list rule failed the tests for that rule.CancelledWhileAFolderIsCheckedAgain_TheFolderStayssent a folder holding a junction to the recorder standing in for the Recycle Bin. The token is cancelled from inside the location check, so the walk sees it before its first folder.AFolderWithAFolderInsideThatCannotBeOpened_IsNotRemovedandFind_DoesNotOfferAFolderItCouldNotLookThroughWholefailed; without the walk recording unreadable folders, the twoSafeFileWalkTestscases failed too. The unopenable folder's name ends in a dot, made through a\\?\path, so an ordinary path cannot list it whatever the account's privileges; a deny entry would not do, since the walk opens folders with backup semantics and an elevated run passes it by.AFolderWhoseNameStartsAnotherRefusedOne_HasItsOwnRefusalShownfailed whileAFolderRefusedAsTheInstallFolder_IsMentionedOnce_WhenItsNameFindsItAgainstill passed. WithoutAppNameset by the search,EveryItem_SaysWhichAppLeftItfailed.