Repository navigation
fix: Windows Features says why a change failed, reads each feature back afterwards, and no longer stops a change half-way - #2940
Merged
Conversation
…ck afterwards, and no longer stops a change half-way - WindowsFeaturesService's change scripts print DISM's error code and the first line of its message before they exit 1, and ParseChange returns both in a FeatureChangeResult. The tab says that reason, in plain words for 0x800F0906, 0x800F081F, 0x800F0907 and 0x80070422, where every failure said "Check permissions". - After every change the view model reads the feature back with ReadFeatureAsync and writes the row from what Windows reports. ReadState counts EnablePending as on and both pending states as waiting for a restart, in a scan too. - WindowsFeature.ResetSwitch turns the switch back whenever a change was declined, refused or failed. - Escape and the Cancel button stop only a scan, while IsScanning is set. They ended DISM part-way through a change. - SafetyDatabase describes MSRDC-Infrastructure, WindowsMediaPlayer and MediaPlayback as the features they are, and rates Windows Sandbox under Containers-DisposableClientVM, its own name.
This was referenced Oct 21, 2026
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.
Closes #2739. Parts 2, 3 and 4 of #2834 for Windows Features.
Confirmed in the code: both change scripts ended in
catch { exit 1 }, so the view model received a barefalseand said "Failed to … Check permissions." for every failure, on a tab that offers a change only to an administrator. After a change it flipped the row'sIsEnabledon success and left it on failure, andParseFeatureListcounted onlyEnabledas on.EscapeCanceland the Cancel button both followedIsBusy, which covers a change, andCancelcancelled the change's token, whichRunProcessAsyncanswers by endingpowershell.exeand itsDismHost.exe. The switch is bound one-way, and nothing told it to readIsEnabledagain when the change did not happen (#2739).What I checked on my PC, without changing anything:
COMExceptionwithHResult0x800F080C, "Feature name … is unknown.", and without administrator rights 0x800702E4, "The requested operation requires elevation.". So the cmdlet's code is in$_.Exception.HResult.Get-WindowsOptionalFeature -Onlinefor every feature took 54 seconds here, and for one feature about a second, so the tab reads back only the feature it changed.Disabled,DisablePending,Enabled,EnablePending,Superseded,PartiallyInstalledandDisabledWithPayloadRemoved.MSRDC-Infrastructure"Remote Differential Compression API Support" ("Installs Remote Differential Compression (RDC) support for use in third-party applications."),Containers-DisposableClientVM"Windows Sandbox",WindowsMediaPlayer"Windows Media Player Legacy (App)" andMediaPlayback"Media Features" ("Controls media features such as Windows Media Player.").Microsoft-Windows-Client-EmbeddedExp-Packageis not on this PC.The changes:
WindowsFeaturesService.ChangeScript: the catch printsFailureMarker, the code in hex and the first line of DISM's message beforeexit 1, andParseChangereturns them in a newFeatureChangeResult. The service logs the refusal.WindowsFeaturesViewModel.DescribeFailure: "Failed to enable X (0x800F081F)." followed by plain words for four codes, three from Microsoft's article on .NET Framework 3.5 installation errors (KB 2734782): files Windows could not download (0x800F0906) or find (0x800F081F) on Windows Update, a policy that forbids downloading them (0x800F0907); and a service it needs that is turned off (0x80070422). Any other code is followed by DISM's own reason, in Windows' language. Nothing says "Check permissions" any more.ReadFeatureAsyncreads one feature through the query the list uses, and after every change the row is written from it: a failure that did part of its work shows what it did, and a success that Windows reports as not having moved says so and suggests a scan. Without a read-back the row goes by DISM's answer, as before.ReadStatecountsEnablePendingas on and both pending states as "Reboot required", in a scan too, and a pending row turns on the reboot notice. A feature waiting for a restart to turn on read as off.WindowsFeature.ResetSwitch, called from afinallyaround the whole command, raises the change notification forIsEnabled, so the switch turns back after a decline, a busy lock, a missing elevation or a failure.EscapeCancelreturnsCancelCommandonly while the newIsScanningis set, the Cancel button shows only then, andCancelcancels only the scan.SafetyDatabase: the hints forMSRDC-Infrastructure,WindowsMediaPlayerandMediaPlaybackdescribe those features in Windows' names, and Windows Sandbox's rating is underContainers-DisposableClientVM.Still open on #2834: part 1 (a change that turns on parent features through
-Allshould name them first and offer them when the feature is turned off), part 3 for Uninstaller and System Fixes, and part 5 (where the admin banner sits).Docs
README, Windows Features: the read-back, the failure reason and Cancel stopping only a scan. ARCHITECTURE:
WindowsFeaturesViewModelandWindowsFeaturesService.Tests
WindowsFeaturesTests: a refusal with 0x800F081F says the plain sentence and its code, another code says DISM's reason, each of the four codes gets its own sentence, a failure with no code says Windows did not say why; a change waiting for a restart shows as on with "Reboot required", a failure that changed the feature shows the change, a failed change that left a restart pending turns on the notice, a success Windows reports as not having moved says so, and without a read-back the row goes by DISM; the switch is told to read the state again after a decline, a busy lock, a missing elevation and a refusal; Escape and Cancel stop a scan and not a change; a scan shows a pending feature as on; the five states;ParseChange;-Allon enable only; and Enable, Disable and the read-back refuse a name that is not a feature name, which nothing tested.SafetyDatabaseTests: the four hints begin with Windows' name for the feature, and Windows Sandbox is rated under its own name only.WindowsFeatureScriptTests(integration) run the change script and the query in Windows PowerShell with the cmdlets shadowed: a refusal prints the marker,800F081Fand the first line and exits 1, andParseChangereads that output; a change that goes through prints the restart flag; and the cmdlet's ownEnablePendingreads as on.EveryCancellableTab_LetsEscapeReachItsOwnCancelCommandholds the Cancel button andEscapeCancelto the same flag.Enabledcounted as on, the read-back ignored, Escape followingIsBusy, Cancel stopping the change, the button followingIsBusy(the guard), the scan ignoring a pending feature, the reboot notice only on success, the old hints, the read-back not checking its name, and-Allon disable.WindowsFeaturesTests,SafetyDatabaseTests,ArchitectureTests,AcceleratorRoutingTests,SystemPathsTestsandInclusiveTermsTests, and the integrationWindowsFeatureScriptTests. All four projects build with 0 warnings, anddotnet format --verify-no-changesis clean. The tab has not been looked at on screen.