diff --git a/Scripts/Features/BackupRegistrySnapshotCapture.ps1 b/Scripts/Features/BackupRegistrySnapshotCapture.ps1 index 286cf44..28bea6c 100644 --- a/Scripts/Features/BackupRegistrySnapshotCapture.ps1 +++ b/Scripts/Features/BackupRegistrySnapshotCapture.ps1 @@ -6,7 +6,7 @@ function Get-RegistryBackupCapturePlans { $planMap = @{} foreach ($feature in $SelectedRegistryFeatures) { - $regFilePath = Get-RegistryFilePathForFeature -Feature $feature -UseSysprepRegFiles:$UseSysprepRegFiles + $regFilePath = Get-RegistryFilePathForFeature -RegistryKey $feature.RegistryKey -UseSysprepRegFiles:$UseSysprepRegFiles if (-not (Test-Path $regFilePath)) { throw "Unable to find registry file for backup: $($feature.RegistryKey) ($regFilePath)" } diff --git a/Scripts/Features/ExecuteChanges.ps1 b/Scripts/Features/ExecuteChanges.ps1 index d79ce44..d959521 100644 --- a/Scripts/Features/ExecuteChanges.ps1 +++ b/Scripts/Features/ExecuteChanges.ps1 @@ -1,11 +1,3 @@ -# List of undo actions to execute after forward changes. -# Each entry is a PSCustomObject with FeatureId and UndoRegFile (filename, without folder prefix). -$script:UndoRegistryKeys = @() - -# List of undo actions for features that do not use registry undo files. -# Each entry is a PSCustomObject with FeatureId. -$script:UndoFeatureActions = @() - # Resolves the path of an undo reg file relative to $script:RegfilesPath. # Checks the Undo/ subfolder first, then falls back to the root Regfiles/ folder. function Resolve-UndoRegFilePath { @@ -218,11 +210,14 @@ function ExecuteAllChanges { } } # Undo operations that write registry values also require a backup - if (-not $hasRegistryBackedFeature -and $script:UndoRegistryKeys.Count -gt 0) { - $hasRegistryBackedFeature = $true + if (-not $hasRegistryBackedFeature) { + foreach ($featureId in $script:UndoParams.Keys) { + $f = if ($script:Features.ContainsKey($featureId)) { $script:Features[$featureId] } else { $null } + if ($f -and $f.RegistryUndoKey) { $hasRegistryBackedFeature = $true; break } + } } - $totalSteps = $actionableKeys.Count + $script:UndoRegistryKeys.Count + $script:UndoFeatureActions.Count + $totalSteps = $actionableKeys.Count + $script:UndoParams.Count if ($hasRegistryBackedFeature) { $totalSteps++ } if ($script:Params.ContainsKey("CreateRestorePoint")) { $totalSteps++ } $currentStep = 0 @@ -235,9 +230,12 @@ function ExecuteAllChanges { Write-Host "> Creating registry backup..." try { - $undoSyntheticFeatures = @($script:UndoRegistryKeys | ForEach-Object { - [PSCustomObject]@{ FeatureId = $_.FeatureId; RegistryKey = (Resolve-UndoRegFilePath $_.UndoRegFile) } - }) + $undoSyntheticFeatures = @($script:UndoParams.Keys | ForEach-Object { + $f = if ($script:Features.ContainsKey($_)) { $script:Features[$_] } else { $null } + if ($f -and $f.RegistryUndoKey) { + [PSCustomObject]@{ FeatureId = $_; RegistryKey = (Resolve-UndoRegFilePath $f.RegistryUndoKey) } + } + } | Where-Object { $_ }) New-RegistrySettingsBackup -ActionableKeys $actionableKeys -ExtraFeatures $undoSyntheticFeatures | Out-Null } catch { @@ -285,37 +283,25 @@ function ExecuteAllChanges { } # Execute all undo operations - foreach ($undoAction in $script:UndoRegistryKeys) { + foreach ($featureId in $script:UndoParams.Keys) { if ($script:CancelRequested) { return } - $undoLabel = if ($script:FeatureLabelLookup) { $script:FeatureLabelLookup[$undoAction.FeatureId] } else { $null } - if (-not $undoLabel) { $undoLabel = $undoAction.FeatureId } + $undoLabel = if ($script:FeatureLabelLookup) { $script:FeatureLabelLookup[$featureId] } else { $null } + if (-not $undoLabel) { $undoLabel = $featureId } $currentStep++ if ($script:ApplyProgressCallback) { & $script:ApplyProgressCallback $currentStep $totalSteps "Undoing: $undoLabel" } - ImportRegistryFile "> Undoing: $undoLabel" (Resolve-UndoRegFilePath $undoAction.UndoRegFile) - } - - foreach ($undoAction in $script:UndoFeatureActions) { - if ($script:CancelRequested) { return } - - $undoLabel = if ($script:FeatureLabelLookup) { $script:FeatureLabelLookup[$undoAction.FeatureId] } else { $null } - if (-not $undoLabel) { $undoLabel = $undoAction.FeatureId } - - $currentStep++ - if ($script:ApplyProgressCallback) { - & $script:ApplyProgressCallback $currentStep $totalSteps "Undoing: $undoLabel" + $f = if ($script:Features.ContainsKey($featureId)) { $script:Features[$featureId] } else { $null } + if ($f -and $f.RegistryUndoKey) { + ImportRegistryFile "> Undoing: $undoLabel" (Resolve-UndoRegFilePath $f.RegistryUndoKey) + } else { + Invoke-UndoFeatureAction -FeatureId $featureId } - - Invoke-UndoFeatureAction -FeatureId $undoAction.FeatureId } - $script:UndoRegistryKeys = @() - $script:UndoFeatureActions = @() - if ($script:RegistryImportFailures -gt 0) { Write-Host "" Write-Host "$($script:RegistryImportFailures) registry import change(s) failed. See output above for details." -ForegroundColor Yellow diff --git a/Scripts/Features/ImportRegistryFile.ps1 b/Scripts/Features/ImportRegistryFile.ps1 index 8df2cbb..626e1be 100644 --- a/Scripts/Features/ImportRegistryFile.ps1 +++ b/Scripts/Features/ImportRegistryFile.ps1 @@ -8,13 +8,7 @@ function ImportRegistryFile { Write-Host $message $usesOfflineHive = $script:Params.ContainsKey("Sysprep") -or $script:Params.ContainsKey("User") - $regFileDirectory = if ($usesOfflineHive) { - Join-Path $script:RegfilesPath "Sysprep" - } - else { - $script:RegfilesPath - } - $regFilePath = Join-Path $regFileDirectory $path + $regFilePath = Get-RegistryFilePathForFeature -RegistryKey $path if (-not (Test-Path $regFilePath)) { $errorMessage = "Unable to find registry file: $path ($regFilePath)" diff --git a/Scripts/GUI/Show-MainWindow.ps1 b/Scripts/GUI/Show-MainWindow.ps1 index 5e7e903..bddef40 100644 --- a/Scripts/GUI/Show-MainWindow.ps1 +++ b/Scripts/GUI/Show-MainWindow.ps1 @@ -2041,11 +2041,6 @@ function Show-MainWindow { } # Apply dynamic tweaks - only controls that changed from their current baseline state - $script:UndoRegistryKeys = @() - $script:UndoFeatureActions = @() - $seenUndoRegistryFeatures = New-Object 'System.Collections.Generic.HashSet[string]' ([System.StringComparer]::OrdinalIgnoreCase) - $seenUndoActionFeatures = New-Object 'System.Collections.Generic.HashSet[string]' ([System.StringComparer]::OrdinalIgnoreCase) - foreach ($tweakAction in @(Get-PendingTweakActions -ShowAppliedTweaksMode:$showAppliedTweaksMode)) { if ($tweakAction.Action -eq 'Apply') { AddParameter $tweakAction.FeatureId @@ -2053,21 +2048,10 @@ function Show-MainWindow { continue } - $featureId = [string]$tweakAction.FeatureId - $feature = if ($script:Features.ContainsKey($featureId)) { $script:Features[$featureId] } else { $null } - if ($feature -and $feature.RegistryUndoKey) { - if ($seenUndoRegistryFeatures.Add($featureId)) { - $script:UndoRegistryKeys += [PSCustomObject]@{ FeatureId = $featureId; UndoRegFile = $feature.RegistryUndoKey } - } - } - elseif ($featureId -in @('DisableStoreSearchSuggestions', 'EnableWindowsSandbox', 'EnableWindowsSubsystemForLinux')) { - if ($seenUndoActionFeatures.Add($featureId)) { - $script:UndoFeatureActions += [PSCustomObject]@{ FeatureId = $featureId } - } - } + $script:UndoParams[[string]$tweakAction.FeatureId] = $true } - if (-not $hasAppSelection -and $selectedForwardFeatureIds.Count -eq 0 -and $script:UndoRegistryKeys.Count -eq 0 -and $script:UndoFeatureActions.Count -eq 0) { + if (-not $hasAppSelection -and $selectedForwardFeatureIds.Count -eq 0 -and $script:UndoParams.Count -eq 0) { Show-MessageBox -Message 'No changes have been selected, please select at least one option to proceed.' -Title 'No Changes Selected' -Button 'OK' -Icon 'Information' return } diff --git a/Scripts/Helpers/RegistryPathHelpers.ps1 b/Scripts/Helpers/RegistryPathHelpers.ps1 index 7795245..be22fa3 100644 --- a/Scripts/Helpers/RegistryPathHelpers.ps1 +++ b/Scripts/Helpers/RegistryPathHelpers.ps1 @@ -67,14 +67,14 @@ function Get-RegistryRootKey { function Get-RegistryFilePathForFeature { param( [Parameter(Mandatory)] - $Feature, + [string]$RegistryKey, [switch]$UseSysprepRegFiles ) $useSysprepLayout = $UseSysprepRegFiles -or $script:Params.ContainsKey('Sysprep') -or $script:Params.ContainsKey('User') if ($useSysprepLayout) { - return Join-Path (Join-Path $script:RegfilesPath 'Sysprep') $Feature.RegistryKey + return Join-Path (Join-Path $script:RegfilesPath 'Sysprep') $RegistryKey } - return Join-Path $script:RegfilesPath $Feature.RegistryKey + return Join-Path $script:RegfilesPath $RegistryKey } diff --git a/Win11Debloat.ps1 b/Win11Debloat.ps1 index 5f404e6..eeee909 100644 --- a/Win11Debloat.ps1 +++ b/Win11Debloat.ps1 @@ -374,6 +374,7 @@ $WinVersion = Get-ItemPropertyValue 'HKLM:\SOFTWARE\Microsoft\Windows NT\Current $script:ModernStandbySupported = CheckModernStandbySupport $script:Params = $PSBoundParameters +$script:UndoParams = @{} # Add default Apps parameter when RemoveApps is requested and Apps was not explicitly provided if ((-not $script:Params.ContainsKey("Apps")) -and $script:Params.ContainsKey("RemoveApps")) {