feat(registry): add GPO override warning and WhatIf dry-run previews (#611)

Co-authored-by: Jeffrey <9938813+Raphire@users.noreply.github.com>
This commit is contained in:
HetCreep
2026-06-22 02:30:31 +07:00
committed by GitHub
parent 82894176d9
commit dfe7810346
16 changed files with 178 additions and 32 deletions

View File

@@ -77,7 +77,9 @@ function ExecuteParameter {
'DisableWidgets' {
Write-Host "> $($feature.ApplyText)..."
# Stop widgets related processes before removing the app packages to prevent potential issues
Get-Process *Widget* -ErrorAction SilentlyContinue | Stop-Process
if (-not $script:Params.ContainsKey("WhatIf")) {
Get-Process *Widget* -ErrorAction SilentlyContinue | Stop-Process
}
RemoveApps @('Microsoft.StartExperiencesApp','MicrosoftWindows.Client.WebExperience','Microsoft.WidgetsPlatformRuntime')
}
@@ -185,18 +187,23 @@ function ExecuteAllChanges {
& $script:ApplyProgressCallback $currentStep $totalSteps "Creating registry backup..."
}
Write-Host "> Creating registry backup..."
try {
$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
if ($script:Params.ContainsKey("WhatIf")) {
Write-Host "[WhatIf] Create registry backup" -ForegroundColor Cyan
}
catch {
throw "Registry backup failed before applying changes. $($_.Exception.Message)"
else {
Write-Host "> Creating registry backup..."
try {
$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 {
throw "Registry backup failed before applying changes. $($_.Exception.Message)"
}
}
}
@@ -206,9 +213,15 @@ function ExecuteAllChanges {
if ($script:ApplyProgressCallback) {
& $script:ApplyProgressCallback $currentStep $totalSteps "Creating system restore point, this may take a moment..."
}
Write-Host "> Creating a system restore point..."
CreateSystemRestorePoint
Write-Host ""
if ($script:Params.ContainsKey("WhatIf")) {
Write-Host "[WhatIf] Create system restore point" -ForegroundColor Cyan
Write-Host ""
}
else {
Write-Host "> Creating a system restore point..."
CreateSystemRestorePoint
Write-Host ""
}
}
# Execute all parameters

View File

@@ -21,6 +21,12 @@ function ImportRegistryFile {
$importScript = {
param($targetRegFilePath, $hiveContext)
if ($script:Params.ContainsKey("WhatIf")) {
Invoke-RegistryOperationsFromRegFile -RegFilePath $targetRegFilePath
Write-Host ""
return
}
# When the target user's hive is already loaded under their SID, the .reg file's
# HKEY_USERS\Default paths won't match. Use the PowerShell registry writer instead,
# which remaps Default → SID via Split-RegistryPath.

View File

@@ -26,6 +26,11 @@ function ReplaceStartMenuForAllUsers {
# Also replace the start menu file for the default user profile
$defaultStartMenuPath = GetUserDirectory -userName "Default" -fileName "AppData\Local\Packages\Microsoft.Windows.StartMenuExperienceHost_cw5n1h2txyewy\LocalState" -exitIfPathNotFound $false
if ($script:Params.ContainsKey("WhatIf")) {
Write-Host "[WhatIf] Replace Start Menu for Default user profile with template $startMenuTemplate" -ForegroundColor Cyan
return
}
# Create folder if it doesn't exist
if (-not (Test-Path $defaultStartMenuPath)) {
new-item $defaultStartMenuPath -ItemType Directory -Force | Out-Null
@@ -61,6 +66,11 @@ function ReplaceStartMenu {
$userName = GetStartMenuUserNameFromPath -StartMenuBinFile $startMenuBinFile
if ($script:Params.ContainsKey("WhatIf")) {
Write-Host "[WhatIf] Replace Start Menu for user $userName with template $startMenuTemplate" -ForegroundColor Cyan
return
}
$backupBinFile = $startMenuBinFile + ".bak"
if (Test-Path $startMenuBinFile) {
@@ -121,6 +131,15 @@ function RestoreStartMenuFromBackup {
}
$currentBinBackup = $StartMenuBinFile + '.restore.bak'
if ($script:Params.ContainsKey("WhatIf")) {
Write-Host "[WhatIf] Restore start menu for user $userName from backup $backupBinFile" -ForegroundColor Cyan
return [PSCustomObject]@{
UserName = $userName
Result = $true
Message = "[WhatIf] Restored start menu for user $userName."
}
}
if (-not (Test-Path -LiteralPath $backupBinFile)) {
return [PSCustomObject]@{
UserName = $userName
@@ -184,19 +203,29 @@ function RestoreStartMenuForAllUsers {
if (Test-Path $defaultStartMenuPath) {
$defaultStartMenuBinFile = Join-Path $defaultStartMenuPath 'start2.bin'
if (Test-Path -LiteralPath $defaultStartMenuBinFile) {
try {
Remove-Item -LiteralPath $defaultStartMenuBinFile -Force
if ($script:Params.ContainsKey("WhatIf")) {
Write-Host "[WhatIf] Remove start2.bin for the default user profile" -ForegroundColor Cyan
$results += [PSCustomObject]@{
UserName = 'Default'
Result = $true
Message = 'Removed start2.bin for the default user profile.'
Message = '[WhatIf] Removed start2.bin for the default user profile.'
}
}
catch {
$results += [PSCustomObject]@{
UserName = 'Default'
Result = $false
Message = "Failed to remove start2.bin for the default user profile. $($_.Exception.Message)"
else {
try {
Remove-Item -LiteralPath $defaultStartMenuBinFile -Force
$results += [PSCustomObject]@{
UserName = 'Default'
Result = $true
Message = 'Removed start2.bin for the default user profile.'
}
}
catch {
$results += [PSCustomObject]@{
UserName = 'Default'
Result = $false
Message = "Failed to remove start2.bin for the default user profile. $($_.Exception.Message)"
}
}
}
}

View File

@@ -5,6 +5,11 @@ function RestartExplorer {
return
}
if ($script:Params.ContainsKey("WhatIf")) {
Write-Host "[WhatIf] Restart the Windows Explorer process" -ForegroundColor Cyan
return
}
Write-Host "> Attempting to restart the Windows Explorer process to apply all changes..."
if ($script:Params.ContainsKey("NoRestartExplorer")) {

View File

@@ -133,6 +133,11 @@ function Restore-RegistryBackupState {
$friendlyTarget = GetFriendlyRegistryBackupTarget -Target ([string]$Backup.Target)
if ($script:Params.ContainsKey("WhatIf")) {
Write-Host "[WhatIf] Restore registry backup for $friendlyTarget" -ForegroundColor Cyan
return [PSCustomObject]@{ Result = $true }
}
$restoreAction = {
param($normalizedBackup)
@@ -148,9 +153,10 @@ function Restore-RegistryBackupState {
Write-Host "Restore requires loading target user hive."
Invoke-WithLoadedRestoreHive -Target $Backup.Target -ScriptBlock $restoreAction -ArgumentObject $Backup
Write-Host "Restore completed for $friendlyTarget."
return
return [PSCustomObject]@{ Result = $true }
}
& $restoreAction $Backup
Write-Host "Restore completed for $friendlyTarget."
return [PSCustomObject]@{ Result = $true }
}

View File

@@ -54,6 +54,11 @@ function DisableStoreSearchSuggestions {
$userName = [regex]::Match($StoreAppsDatabase, '(?:Users\\)([^\\]+)(?:\\AppData)').Groups[1].Value
if (-not $userName) { $userName = '<unknown>' }
if ($script:Params.ContainsKey("WhatIf")) {
Write-Host "[WhatIf] Disable Microsoft Store search suggestions for user $userName by restricting access to ${StoreAppsDatabase}" -ForegroundColor Cyan
return
}
# This file doesn't exist in EEA (No Store app suggestions).
if (-not (Test-Path -Path $StoreAppsDatabase))
{
@@ -132,6 +137,11 @@ function EnableStoreSearchSuggestions {
$userName = [regex]::Match($StoreAppsDatabase, '(?:Users\\)([^\\]+)(?:\\AppData)').Groups[1].Value
if (-not $userName) { $userName = '<unknown>' }
if ($script:Params.ContainsKey("WhatIf")) {
Write-Host "[WhatIf] Re-enable Microsoft Store search suggestions for user $userName by restoring access to ${StoreAppsDatabase}" -ForegroundColor Cyan
return
}
if (-not (Test-Path -Path $StoreAppsDatabase)) {
Write-Host "Store app database not found for user $userName, nothing to undo"
return
@@ -245,7 +255,8 @@ function Test-StoreSearchSuggestionsDisabled {
$isEveryone = $false
try {
$isEveryone = $accessRule.IdentityReference.Translate([System.Security.Principal.SecurityIdentifier]) -eq $everyoneSid
} catch { }
}
catch { }
if ($isEveryone) {
return $true

View File

@@ -4,6 +4,12 @@ function EnableWindowsFeature {
[string]$FeatureName
)
if ($script:Params.ContainsKey("WhatIf")) {
Write-Host "[WhatIf] Enable Windows feature: $FeatureName" -ForegroundColor Cyan
Write-Host ""
return
}
$result = Invoke-NonBlocking -ScriptBlock {
param($name)
Enable-WindowsOptionalFeature -Online -FeatureName $name -All -NoRestart
@@ -21,6 +27,12 @@ function DisableWindowsFeature {
[string]$FeatureName
)
if ($script:Params.ContainsKey("WhatIf")) {
Write-Host "[WhatIf] Disable Windows feature: $FeatureName" -ForegroundColor Cyan
Write-Host ""
return
}
$result = Invoke-NonBlocking -ScriptBlock {
param($name)
Disable-WindowsOptionalFeature -Online -FeatureName $name -NoRestart