Add registry backup & restore (#566)

Starting from this commit, Win11Debloat will automatically create a registry backup every time the script is run. This registry backup can be used to revert any registry changes made by the script.
This commit is contained in:
Jeffrey
2026-05-08 21:19:52 +02:00
committed by GitHub
parent 11a324365d
commit 2c360961e3
37 changed files with 3193 additions and 719 deletions

View File

@@ -96,6 +96,7 @@ function Show-MainWindow {
$menuAbout = $window.FindName('MenuAbout')
$importConfigBtn = $window.FindName('ImportConfigBtn')
$exportConfigBtn = $window.FindName('ExportConfigBtn')
$restoreBackupBtn = $window.FindName('RestoreBackupBtn')
$windowStateNormal = [System.Windows.WindowState]::Normal
$windowStateMaximized = [System.Windows.WindowState]::Maximized
@@ -234,7 +235,7 @@ function Show-MainWindow {
})
$menuLogs.Add_Click({
$logsFolder = Join-Path $PSScriptRoot "../../Logs"
$logsFolder = Join-Path (Split-Path (Split-Path $PSScriptRoot -Parent) -Parent) 'Logs'
if (Test-Path $logsFolder) {
Start-Process "explorer.exe" -ArgumentList $logsFolder
}
@@ -247,22 +248,45 @@ function Show-MainWindow {
Show-AboutDialog -Owner $window
})
# --- Import/Export Configuration ---
$exportConfigBtn.Add_Click({
Export-Configuration -Owner $window -UsesDarkMode $usesDarkMode -AppsPanel $appsPanel -UiControlMappings $script:UiControlMappings -UserSelectionCombo $userSelectionCombo -OtherUsernameTextBox $otherUsernameTextBox
try {
Export-Configuration -Owner $window -UsesDarkMode $usesDarkMode -AppsPanel $appsPanel -UiControlMappings $script:UiControlMappings -UserSelectionCombo $userSelectionCombo -OtherUsernameTextBox $otherUsernameTextBox
}
catch {
Write-Warning "Export configuration failed: $($_.Exception.Message)"
Show-MessageBox -Owner $window -Message "Unable to open export configuration dialog: $($_.Exception.Message)" -Title 'Export Configuration Failed' -Button 'OK' -Icon 'Error' | Out-Null
}
})
$importConfigBtn.Add_Click({
Import-Configuration -Owner $window -UsesDarkMode $usesDarkMode -AppsPanel $appsPanel -UiControlMappings $script:UiControlMappings -UserSelectionCombo $userSelectionCombo -OtherUsernameTextBox $otherUsernameTextBox -OnAppsImported { UpdateAppSelectionStatus; UpdatePresetStates } -OnImportCompleted {
$tabControl.SelectedIndex = 3
UpdateNavigationButtons
try {
Import-Configuration -Owner $window -UsesDarkMode $usesDarkMode -AppsPanel $appsPanel -UiControlMappings $script:UiControlMappings -UserSelectionCombo $userSelectionCombo -OtherUsernameTextBox $otherUsernameTextBox -OnAppsImported { UpdateAppSelectionStatus; UpdatePresetStates } -OnImportCompleted {
$tabControl.SelectedIndex = 3
UpdateNavigationButtons
$window.Dispatcher.BeginInvoke([System.Windows.Threading.DispatcherPriority]::Loaded, [action]{
Show-Bubble -TargetControl $reviewChangesBtn -Message 'View the selected changes here'
}) | Out-Null
$window.Dispatcher.BeginInvoke([System.Windows.Threading.DispatcherPriority]::Loaded, [action]{
Show-Bubble -TargetControl $reviewChangesBtn -Message 'View the selected changes here'
}) | Out-Null
}
}
catch {
Write-Warning "Import configuration failed: $($_.Exception.Message)"
Show-MessageBox -Owner $window -Message "Unable to open import configuration dialog: $($_.Exception.Message)" -Title 'Import Configuration Failed' -Button 'OK' -Icon 'Error' | Out-Null
}
})
if ($restoreBackupBtn) {
$restoreBackupBtn.Add_Click({
try {
Show-RestoreBackupWindow -Owner $window
}
catch {
Write-Warning "Restore backup action failed: $($_.Exception.Message)"
Show-MessageBox -Owner $window -Message "Unable to open restore backup dialog: $($_.Exception.Message)" -Title 'Restore Backup Failed' -Button 'OK' -Icon 'Error' | Out-Null
}
})
}
$closeBtn.Add_Click({
$window.Close()
})
@@ -352,6 +376,20 @@ function Show-MainWindow {
}
}
function ClearTweakSelections {
if (-not $script:UiControlMappings) { return }
foreach ($controlName in $script:UiControlMappings.Keys) {
$control = $window.FindName($controlName)
if ($control -is [System.Windows.Controls.CheckBox]) {
$control.IsChecked = $false
}
elseif ($control -is [System.Windows.Controls.ComboBox]) {
$control.SelectedIndex = 0
}
}
}
function AnimateDropdownArrow {
param(
[System.Windows.Controls.TextBlock]$arrow,
@@ -843,7 +881,7 @@ function Show-MainWindow {
if ($feature.FeatureId -match '^Disable') { $opt = 'Disable' } elseif ($feature.FeatureId -match '^Enable') { $opt = 'Enable' }
$items = @('No Change', $opt)
$comboName = ("Feature_{0}_Combo" -f $feature.FeatureId) -replace '[^a-zA-Z0-9_]',''
$combo = CreateLabeledCombo -parent $panel -labelText ($feature.Action + ' ' + $feature.Label) -comboName $comboName -items $items
$combo = CreateLabeledCombo -parent $panel -labelText $feature.Label -comboName $comboName -items $items
# attach tooltip from Features.json if present
if ($feature.ToolTip) {
$tipBlock = New-Object System.Windows.Controls.TextBlock
@@ -855,7 +893,7 @@ function Show-MainWindow {
try { $lblBorderObj = $window.FindName("$comboName`_LabelBorder") } catch {}
if ($lblBorderObj) { $lblBorderObj.ToolTip = $tipBlock }
}
$script:UiControlMappings[$comboName] = @{ Type='feature'; FeatureId = $feature.FeatureId; Action = $feature.Action; Label = $feature.Label; Category = $categoryName }
$script:UiControlMappings[$comboName] = @{ Type='feature'; FeatureId = $feature.FeatureId; Label = $feature.Label; Category = $categoryName }
}
}
}
@@ -863,7 +901,7 @@ function Show-MainWindow {
# Build a feature-label lookup so GenerateOverview can resolve feature IDs without reloading JSON
$script:FeatureLabelLookup = @{}
foreach ($f in $featuresJson.Features) {
$script:FeatureLabelLookup[$f.FeatureId] = $f.Action + ' ' + $f.Label
$script:FeatureLabelLookup[$f.FeatureId] = $f.Label
}
}
@@ -1508,8 +1546,6 @@ function Show-MainWindow {
# Show "Current user only" option, hide "Target user only" option
$appRemovalScopeCurrentUser.Visibility = 'Visible'
$appRemovalScopeTargetUser.Visibility = 'Collapsed'
# Enable app removal scope selection for current user
$appRemovalScopeCombo.IsEnabled = $true
$appRemovalScopeCombo.SelectedIndex = 0
}
1 {
@@ -1519,8 +1555,6 @@ function Show-MainWindow {
# Hide "Current user only" option, show "Target user only" option
$appRemovalScopeCurrentUser.Visibility = 'Collapsed'
$appRemovalScopeTargetUser.Visibility = 'Visible'
# Enable app removal scope selection for other user
$appRemovalScopeCombo.IsEnabled = $true
$appRemovalScopeCombo.SelectedIndex = 0
}
2 {
@@ -1531,10 +1565,12 @@ function Show-MainWindow {
$appRemovalScopeCurrentUser.Visibility = 'Collapsed'
$appRemovalScopeTargetUser.Visibility = 'Collapsed'
# Lock app removal scope to "All users" when applying to sysprep
$appRemovalScopeCombo.IsEnabled = $false
$appRemovalScopeCombo.SelectedIndex = 0
}
}
# Keep enabled/disabled state in sync with both app selection and user mode.
UpdateAppSelectionStatus
})
# Helper function to update app removal scope description
@@ -1577,38 +1613,16 @@ function Show-MainWindow {
return $true
}
$username = $otherUsernameTextBox.Text.Trim()
$errorBrush = $window.Resources['ValidationErrorColor']
$successBrush = $window.Resources['ValidationSuccessColor']
$validationResult = Test-TargetUserName -UserName $otherUsernameTextBox.Text
if ($username.Length -eq 0) {
$usernameValidationMessage.Text = "Please enter a username"
$usernameValidationMessage.Foreground = $errorBrush
return $false
}
if ($username -eq $env:USERNAME) {
$usernameValidationMessage.Text = "Cannot enter your own username, use 'Current User' option instead"
$usernameValidationMessage.Foreground = $errorBrush
return $false
}
$userExists = CheckIfUserExists -Username $username
if ($userExists) {
if (TestIfUserIsLoggedIn -Username $username) {
$usernameValidationMessage.Text = "User '$username' is currently logged in. Please sign out that user first."
$usernameValidationMessage.Foreground = $errorBrush
return $false
}
$usernameValidationMessage.Text = "User found: $username"
$usernameValidationMessage.Text = $validationResult.Message
if ($validationResult.IsValid) {
$usernameValidationMessage.Foreground = $successBrush
return $true
}
$usernameValidationMessage.Text = "User not found, please enter a valid username"
$usernameValidationMessage.Foreground = $errorBrush
return $false
}
@@ -1655,7 +1669,7 @@ function Show-MainWindow {
}
elseif ($mapping.Type -eq 'feature') {
$label = $script:FeatureLabelLookup[$mapping.FeatureId]
if (-not $label) { $label = $mapping.Action + ' ' + $mapping.Label }
if (-not $label) { $label = $mapping.Label }
$changesList += $label
}
}
@@ -2210,18 +2224,7 @@ function Show-MainWindow {
# Clear All Tweaks button
$clearAllTweaksBtn = $window.FindName('ClearAllTweaksBtn')
$clearAllTweaksBtn.Add_Click({
# Reset all ComboBoxes to index 0 (No Change) and uncheck all CheckBoxes
if ($script:UiControlMappings) {
foreach ($comboName in $script:UiControlMappings.Keys) {
$control = $window.FindName($comboName)
if ($control -is [System.Windows.Controls.CheckBox]) {
$control.IsChecked = $false
}
elseif ($control -is [System.Windows.Controls.ComboBox]) {
$control.SelectedIndex = 0
}
}
}
ClearTweakSelections
UpdateTweakPresetStates
})