3 Commits

Author SHA1 Message Date
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
5 changed files with 29 additions and 11 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

@@ -170,7 +170,12 @@ function ExecuteAllChanges {
} }
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)

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

@@ -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'