6 Commits

Author SHA1 Message Date
Jeffrey
2a5cb986c9 Merge branch 'master' of https://github.com/Raphire/Win11Debloat 2026-05-17 17:56:01 +02:00
Jeffrey
66982ada28 Limit backup restore files to json only 2026-05-17 17:55:59 +02:00
Ahmad Z. Shatnawi
489af33a8b Fix: Increase System Restore point creation timeout to 90 seconds (#586) 2026-05-17 17:50:36 +02:00
Jeffrey
51aa288dfd Bump version 2026-05-12 00:01:57 +02:00
Jeffrey
24a6f1bcf8 Fix capture and restore of signed dword/qword registry values
Co-authored-by: Copilot <copilot@github.com>
2026-05-11 19:14:08 +02:00
Jeffrey
8ac664e45f Add restart instructions to registry restore success message 2026-05-10 23:26:22 +02:00
7 changed files with 36 additions and 18 deletions

View File

@@ -226,12 +226,19 @@ function Convert-RegistryValueToSnapshot {
$valueKind = $RegistryKey.GetValueKind($ValueName) $valueKind = $RegistryKey.GetValueKind($ValueName)
$value = $RegistryKey.GetValue($ValueName, $null, [Microsoft.Win32.RegistryValueOptions]::DoNotExpandEnvironmentNames) $value = $RegistryKey.GetValue($ValueName, $null, [Microsoft.Win32.RegistryValueOptions]::DoNotExpandEnvironmentNames)
$normalizedValue = switch ($valueKind) { try {
([Microsoft.Win32.RegistryValueKind]::Binary) { @($value | ForEach-Object { [int]$_ }) } $normalizedValue = switch ($valueKind) {
([Microsoft.Win32.RegistryValueKind]::MultiString) { @($value) } ([Microsoft.Win32.RegistryValueKind]::Binary) { @($value | ForEach-Object { [int]$_ }) }
([Microsoft.Win32.RegistryValueKind]::DWord) { [uint32]$value } ([Microsoft.Win32.RegistryValueKind]::MultiString) { @($value) }
([Microsoft.Win32.RegistryValueKind]::QWord) { [uint64]$value } ([Microsoft.Win32.RegistryValueKind]::DWord) { [BitConverter]::ToUInt32([BitConverter]::GetBytes([int32]$value), 0) }
default { if ($null -ne $value) { [string]$value } else { $null } } ([Microsoft.Win32.RegistryValueKind]::QWord) { [BitConverter]::ToUInt64([BitConverter]::GetBytes([int64]$value), 0) }
default { if ($null -ne $value) { [string]$value } else { $null } }
}
}
catch {
$valueType = if ($null -ne $value) { $value.GetType().FullName } else { '<null>' }
$valueForLog = if ($null -eq $value) { '<null>' } elseif ($value -is [array]) { ($value -join ',') } else { [string]$value }
throw "Failed to normalize registry value for backup. Key='$($RegistryKey.Name)' Name='$ValueName' Kind='$valueKind' RawType='$valueType' RawValue='$valueForLog'. InnerError: $($_.Exception.Message)"
} }
return @{ return @{

View File

@@ -6,7 +6,7 @@ function CreateSystemRestorePoint {
# In GUI mode, skip the prompt and just try to enable it # In GUI mode, skip the prompt and just try to enable it
if ($script:GuiWindow -or $Silent -or $( Read-Host -Prompt "System restore is disabled, would you like to enable it and create a restore point? (y/n)") -eq 'y') { if ($script:GuiWindow -or $Silent -or $( Read-Host -Prompt "System restore is disabled, would you like to enable it and create a restore point? (y/n)") -eq 'y') {
try { try {
$enableResult = Invoke-NonBlocking -TimeoutSeconds 20 -ScriptBlock { $enableResult = Invoke-NonBlocking -TimeoutSeconds 90 -ScriptBlock {
try { try {
Enable-ComputerRestore -Drive "$env:SystemDrive" Enable-ComputerRestore -Drive "$env:SystemDrive"
return $null return $null
@@ -33,7 +33,7 @@ function CreateSystemRestorePoint {
if (-not $failed) { if (-not $failed) {
try { try {
$result = Invoke-NonBlocking -TimeoutSeconds 20 -ScriptBlock { $result = Invoke-NonBlocking -TimeoutSeconds 90 -ScriptBlock {
try { try {
$recentRestorePoints = Get-ComputerRestorePoint | Where-Object { (Get-Date) - [System.Management.ManagementDateTimeConverter]::ToDateTime($_.CreationTime) -le (New-TimeSpan -Hours 24) } $recentRestorePoints = Get-ComputerRestorePoint | Where-Object { (Get-Date) - [System.Management.ManagementDateTimeConverter]::ToDateTime($_.CreationTime) -le (New-TimeSpan -Hours 24) }
} }
@@ -92,4 +92,4 @@ function CreateSystemRestorePoint {
Write-Host "Warning: Continuing without restore point" -ForegroundColor Yellow Write-Host "Warning: Continuing without restore point" -ForegroundColor Yellow
} }
} }

View File

@@ -166,20 +166,25 @@ function ExecuteAllChanges {
if ($hasRegistryBackedFeature) { if ($hasRegistryBackedFeature) {
$currentStep++ $currentStep++
if ($script:ApplyProgressCallback) { if ($script:ApplyProgressCallback) {
& $script:ApplyProgressCallback $currentStep $totalSteps "Creating registry backup" & $script:ApplyProgressCallback $currentStep $totalSteps "Creating registry backup..."
} }
Write-Host "> Creating registry backup..." Write-Host "> Creating registry backup..."
New-RegistrySettingsBackup -ActionableKeys $actionableKeys | Out-Null try {
New-RegistrySettingsBackup -ActionableKeys $actionableKeys | Out-Null
}
catch {
throw "Registry backup failed before applying changes. $($_.Exception.Message)"
}
} }
# Create restore point if requested (CLI only - GUI handles this separately) # Create restore point if requested (CLI only - GUI handles this separately)
if ($script:Params.ContainsKey("CreateRestorePoint")) { if ($script:Params.ContainsKey("CreateRestorePoint")) {
$currentStep++ $currentStep++
if ($script:ApplyProgressCallback) { if ($script:ApplyProgressCallback) {
& $script:ApplyProgressCallback $currentStep $totalSteps "Creating system restore point" & $script:ApplyProgressCallback $currentStep $totalSteps "Creating system restore point, this may take a moment..."
} }
Write-Host "> Attempting to create a system restore point..." Write-Host "> Creating a system restore point..."
CreateSystemRestorePoint CreateSystemRestorePoint
Write-Host "" Write-Host ""
} }

View File

@@ -157,8 +157,14 @@ function Convert-RegistryValueDataFromBackup {
) )
switch ($Kind) { switch ($Kind) {
([Microsoft.Win32.RegistryValueKind]::DWord) { return [uint32]$Data } ([Microsoft.Win32.RegistryValueKind]::DWord) {
([Microsoft.Win32.RegistryValueKind]::QWord) { return [uint64]$Data } $unsigned = [uint32]$Data
return [BitConverter]::ToInt32([BitConverter]::GetBytes($unsigned), 0)
}
([Microsoft.Win32.RegistryValueKind]::QWord) {
$unsigned = [uint64]$Data
return [BitConverter]::ToInt64([BitConverter]::GetBytes($unsigned), 0)
}
([Microsoft.Win32.RegistryValueKind]::MultiString) { return @($Data | ForEach-Object { [string]$_ }) } ([Microsoft.Win32.RegistryValueKind]::MultiString) { return @($Data | ForEach-Object { [string]$_ }) }
([Microsoft.Win32.RegistryValueKind]::Binary) { ([Microsoft.Win32.RegistryValueKind]::Binary) {
$bytes = Convert-BackupDataToByteArray -Data $Data $bytes = Convert-BackupDataToByteArray -Data $Data

View File

@@ -255,7 +255,7 @@ function Show-RestoreBackupDialog {
$openDialog = New-Object Microsoft.Win32.OpenFileDialog $openDialog = New-Object Microsoft.Win32.OpenFileDialog
$openDialog.Title = 'Select Registry Backup File' $openDialog.Title = 'Select Registry Backup File'
$openDialog.Filter = 'Registry backup (*.json)|*.json|All files (*.*)|*.*' $openDialog.Filter = 'Registry backup (*.json)|*.json'
$openDialog.DefaultExt = '.json' $openDialog.DefaultExt = '.json'
$openDialog.InitialDirectory = $script:RegistryBackupsPath $openDialog.InitialDirectory = $script:RegistryBackupsPath

View File

@@ -24,7 +24,7 @@ function Show-RestoreBackupWindow {
Write-Host "User confirmed registry restore for $($backup.Target)." Write-Host "User confirmed registry restore for $($backup.Target)."
Restore-RegistryBackupState -Backup $backup Restore-RegistryBackupState -Backup $backup
$successMessage = 'Registry backup restored successfully.' $successMessage = 'Registry backup restored successfully. Please restart your computer for all changes to take effect.'
} }
elseif ($dialogResult.Result -eq 'RestoreStartMenu') { elseif ($dialogResult.Result -eq 'RestoreStartMenu') {
$scope = $dialogResult.StartMenuScope $scope = $dialogResult.StartMenuScope

View File

@@ -141,7 +141,7 @@ if (-not $isAdmin) {
} }
# Define script-level variables & paths # Define script-level variables & paths
$script:Version = "2026.05.10" $script:Version = "2026.05.11"
$configPath = Join-Path $PSScriptRoot 'Config' $configPath = Join-Path $PSScriptRoot 'Config'
$logsPath = Join-Path $PSScriptRoot 'Logs' $logsPath = Join-Path $PSScriptRoot 'Logs'
$schemasPath = Join-Path $PSScriptRoot 'Schemas' $schemasPath = Join-Path $PSScriptRoot 'Schemas'