mirror of
https://github.com/ChrisTitusTech/winutil.git
synced 2026-08-10 10:01:16 +10:00
* refactor: make MPO tweak a three-state control * docs: explain MPO tweak states * docs: address code review comments * refactor: make Multiplane Overlay config-driven
79 lines
3.4 KiB
PowerShell
79 lines
3.4 KiB
PowerShell
function Set-WinUtilRegistryComboState {
|
|
<#
|
|
.SYNOPSIS
|
|
Applies and verifies a config-defined registry combo-box state.
|
|
|
|
.PARAMETER Registry
|
|
Registry settings containing a value mapping for each supported state.
|
|
|
|
.PARAMETER State
|
|
The state name to apply.
|
|
#>
|
|
param(
|
|
[Parameter(Mandatory)]
|
|
$Registry,
|
|
|
|
[Parameter(Mandatory)]
|
|
[string]$State
|
|
)
|
|
|
|
if ($Registry[0].Values.PSObject.Properties.Name -notcontains $State) {
|
|
throw "Unknown registry state '$State'."
|
|
}
|
|
|
|
# Preserve exact prior values so a partial update can be rolled back.
|
|
$previousValues = foreach ($setting in @($Registry)) {
|
|
$currentValue = Get-WinUtilRegistryComboValue -Setting $setting
|
|
[pscustomobject]@{ Setting = $setting; Exists = $currentValue.Exists; Value = $currentValue.Value }
|
|
}
|
|
|
|
try {
|
|
foreach ($setting in @($Registry)) {
|
|
$configuredValue = $setting.Values.PSObject.Properties[$State].Value
|
|
$previousValue = $previousValues | Where-Object Setting -EQ $setting
|
|
if ($configuredValue -ne "<RemoveEntry>" -or $previousValue.Exists) {
|
|
Set-WinUtilRegistry -Name $setting.Name -Path $setting.Path -Type $setting.Type -Value $configuredValue
|
|
}
|
|
}
|
|
|
|
# Set-WinUtilRegistry reports write errors without throwing, so verify each result explicitly.
|
|
foreach ($setting in @($Registry)) {
|
|
$configuredValue = $setting.Values.PSObject.Properties[$State].Value
|
|
$currentValue = Get-WinUtilRegistryComboValue -Setting $setting
|
|
$writeMatches = if ($configuredValue -eq "<RemoveEntry>") {
|
|
-not $currentValue.Exists
|
|
} else {
|
|
$currentValue.Exists -and [string]$currentValue.Value -eq [string]$configuredValue
|
|
}
|
|
if (-not $writeMatches) {
|
|
throw "The registry values did not match the requested state."
|
|
}
|
|
}
|
|
} catch {
|
|
$applyError = $_.Exception.Message
|
|
if ([string]::IsNullOrWhiteSpace($applyError)) {
|
|
$applyError = "The registry values did not match the requested state."
|
|
}
|
|
$rollbackFailed = $false
|
|
foreach ($previousValue in $previousValues) {
|
|
try {
|
|
$currentValue = Get-WinUtilRegistryComboValue -Setting $previousValue.Setting
|
|
if ($previousValue.Exists -or $currentValue.Exists) {
|
|
$rollbackValue = if ($previousValue.Exists) { $previousValue.Value } else { "<RemoveEntry>" }
|
|
Set-WinUtilRegistry -Name $previousValue.Setting.Name -Path $previousValue.Setting.Path -Type $previousValue.Setting.Type -Value $rollbackValue
|
|
}
|
|
$restoredValue = Get-WinUtilRegistryComboValue -Setting $previousValue.Setting
|
|
if ($restoredValue.Exists -ne $previousValue.Exists -or ($restoredValue.Exists -and [string]$restoredValue.Value -ne [string]$previousValue.Value)) {
|
|
$rollbackFailed = $true
|
|
}
|
|
} catch {
|
|
$rollbackFailed = $true
|
|
}
|
|
}
|
|
if ($rollbackFailed) {
|
|
throw "Unable to apply registry state '$State': $applyError. The previous registry state could not be restored."
|
|
}
|
|
throw "Unable to apply registry state '$State': $applyError"
|
|
}
|
|
}
|