#Requires -RunAsAdministrator <# .SYNOPSIS Interactive Windows Registry Settings Manager .DESCRIPTION Displays Windows registry settings in a navigable TUI menu. Use UP/DOWN arrows to move between settings, LEFT/RIGHT to toggle values. Changes are applied immediately to the registry. Some system-level settings require Administrator privileges. .NOTES Based on registry paths from WinSetup.ps1 #> # ───────────────────────────────────────────────────────────────────────────── # REGION: Data model – each setting is a hashtable describing its registry # location, value name, the two toggle states, and display metadata. # ───────────────────────────────────────────────────────────────────────────── $Settings = @( # ── Explorer Advanced ───────────────────────────────────────────────────── @{ Group = "Explorer Advanced [User]" Label = "Explorer window opens to" Path = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced" ValueName = "LaunchTo" States = @("This PC", "Quick Access") StateValues = @(1, 2) OnValue = 1 # value that matches States[0] Type = "DWORD" }, @{ Group = "Explorer Advanced [User]" Label = "File extensions" Path = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced" ValueName = "HideFileExt" States = @("Show", "Hide") StateValues = @(0, 1) OnValue = 0 Type = "DWORD" }, @{ Group = "Explorer Advanced [User]" Label = "Taskbar Chat icon" Path = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced" ValueName = "TaskbarMn" States = @("Hide", "Show") StateValues = @(0, 1) OnValue = 0 Type = "DWORD" }, @{ Group = "Explorer Advanced [User]" Label = "Taskbar Widgets" Path = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced" ValueName = "TaskbarDa" States = @("Hide", "Show") StateValues = @(0, 1) OnValue = 0 Type = "DWORD" }, @{ Group = "Explorer Advanced [User]" Label = "Taskbar Copilot icon" Path = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced" ValueName = "ShowCopilotButton" States = @("Hide", "Show") StateValues = @(0, 1) OnValue = 0 Type = "DWORD" }, @{ Group = "Explorer Advanced [User]" Label = "Telemetry (Start_TrackProgs)" Path = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced" ValueName = "Start_TrackProgs" States = @("Disabled", "Enabled") StateValues = @(0, 1) OnValue = 0 Type = "DWORD" }, @{ Group = "Explorer Advanced [User]" Label = "Tips & Suggestions (IrisRecommendations)" Path = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced" ValueName = "Start_IrisRecommendations" States = @("Disabled", "Enabled") StateValues = @(0, 1) OnValue = 0 Type = "DWORD" }, @{ Group = "Explorer Advanced [User]" Label = "Sync Provider Notifications" Path = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced" ValueName = "ShowSyncProviderNotifications" States = @("Disabled", "Enabled") StateValues = @(0, 1) OnValue = 0 Type = "DWORD" }, # ── Windows Search ──────────────────────────────────────────────────────── @{ Group = "Windows Search [User]" Label = "Bing Search in Start" Path = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Search" ValueName = "BingSearchEnabled" States = @("Disabled", "Enabled") StateValues = @(0, 1) OnValue = 0 Type = "DWORD" }, @{ Group = "Windows Search [User]" Label = "Search Box Taskbar Mode" Path = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Search" ValueName = "SearchboxTaskbarMode" States = @("Hidden", "Visible") StateValues = @(0, 1) OnValue = 0 Type = "DWORD" }, # ── Explorer Policy ─────────────────────────────────────────────────────── @{ Group = "Explorer Policy [User]" Label = "Disable Search Box Suggestions" Path = "HKCU:\Software\Policies\Microsoft\Windows\Explorer" ValueName = "DisableSearchBoxSuggestions" States = @("Disabled (suggestions off)", "Enabled (suggestions on)") StateValues = @(1, 0) OnValue = 1 Type = "DWORD" CreatePathIfAbsent = $true }, # ── Personalisation ─────────────────────────────────────────────────────── @{ Group = "Personalisation [User]" Label = "Apps Theme" Path = "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Themes\Personalize" ValueName = "AppsUseLightTheme" States = @("Dark", "Light") StateValues = @(0, 1) OnValue = 0 Type = "DWORD" }, @{ Group = "Personalisation [User]" Label = "System Theme" Path = "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Themes\Personalize" ValueName = "SystemUsesLightTheme" States = @("Dark", "Light") StateValues = @(0, 1) OnValue = 0 Type = "DWORD" }, @{ Group = "Personalisation Settings [User]" Label = "Accepted Privacy Policy" Path = "HKCU:\Software\Microsoft\Personalization\Settings" ValueName = "AcceptedPrivacyPolicy" States = @("No", "Yes") StateValues = @(0, 1) OnValue = 0 Type = "DWORD" }, # ── Advertising ─────────────────────────────────────────────────────────── @{ Group = "Advertising Info [User]" Label = "Advertising ID" Path = "HKCU:\Software\Microsoft\Windows\CurrentVersion\AdvertisingInfo" ValueName = "Enabled" States = @("Disabled", "Enabled") StateValues = @(0, 1) OnValue = 0 Type = "DWORD" }, # ── Privacy ─────────────────────────────────────────────────────────────── @{ Group = "Privacy [User]" Label = "Tailored Experiences with Diagnostic Data" Path = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Privacy" ValueName = "TailoredExperiencesWithDiagnosticDataEnabled" States = @("Disabled", "Enabled") StateValues = @(0, 1) OnValue = 0 Type = "DWORD" }, # ── Content Delivery Manager ────────────────────────────────────────────── @{ Group = "Content Delivery [User]" Label = "Suggested Apps (338388)" Path = "HKCU:\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" ValueName = "SubscribedContent-338388Enabled" States = @("Disabled", "Enabled") StateValues = @(0, 1) OnValue = 0 Type = "DWORD" }, @{ Group = "Content Delivery [User]" Label = "Suggested Apps (338389)" Path = "HKCU:\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" ValueName = "SubscribedContent-338389Enabled" States = @("Disabled", "Enabled") StateValues = @(0, 1) OnValue = 0 Type = "DWORD" }, @{ Group = "Content Delivery [User]" Label = "Start Menu Suggestions (338393)" Path = "HKCU:\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" ValueName = "SubscribedContent-338393Enabled" States = @("Disabled", "Enabled") StateValues = @(0, 1) OnValue = 0 Type = "DWORD" }, @{ Group = "Content Delivery [User]" Label = "Tips & Tricks (353694)" Path = "HKCU:\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" ValueName = "SubscribedContent-353694Enabled" States = @("Disabled", "Enabled") StateValues = @(0, 1) OnValue = 0 Type = "DWORD" }, @{ Group = "Content Delivery [User]" Label = "Tips & Tricks (353696)" Path = "HKCU:\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" ValueName = "SubscribedContent-353696Enabled" States = @("Disabled", "Enabled") StateValues = @(0, 1) OnValue = 0 Type = "DWORD" }, @{ Group = "Content Delivery [User]" Label = "System Pane Suggestions" Path = "HKCU:\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" ValueName = "SystemPaneSuggestionsEnabled" States = @("Disabled", "Enabled") StateValues = @(0, 1) OnValue = 0 Type = "DWORD" }, @{ Group = "Content Delivery [User]" Label = "Soft Landing (Feature Highlights)" Path = "HKCU:\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" ValueName = "SoftLandingEnabled" States = @("Disabled", "Enabled") StateValues = @(0, 1) OnValue = 0 Type = "DWORD" }, @{ Group = "Content Delivery [User]" Label = "Silent App Installs" Path = "HKCU:\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" ValueName = "SilentInstalledAppsEnabled" States = @("Disabled", "Enabled") StateValues = @(0, 1) OnValue = 0 Type = "DWORD" }, # ── Mobility ────────────────────────────────────────────────────────────── @{ Group = "Mobility [User]" Label = "Mobile Plans Opt-In" Path = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Mobility" ValueName = "OptedIn" States = @("Disabled", "Enabled") StateValues = @(0, 1) OnValue = 0 Type = "DWORD" }, # ── Notifications ───────────────────────────────────────────────────────── @{ Group = "Notifications [User]" Label = "Suggested App Toasts" Path = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Notifications\Settings\Windows.SystemToast.Suggested" ValueName = "Enabled" States = @("Disabled", "Enabled") StateValues = @(0, 1) OnValue = 0 Type = "DWORD" CreatePathIfAbsent = $true }, # ── Engagement ──────────────────────────────────────────────────────────── @{ Group = "Engagement [User]" Label = "Scoobe System Setting (OOBE prompts)" Path = "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\UserProfileEngagement" ValueName = "ScoobeSystemSettingEnabled" States = @("Disabled", "Enabled") StateValues = @(0, 1) OnValue = 0 Type = "DWORD" }, # ── Speech ──────────────────────────────────────────────────────────────── @{ Group = "Speech [User]" Label = "Online Speech Recognition" Path = "HKCU:\Software\Microsoft\Speech_OneCore\Settings\OnlineSpeechPrivacy" ValueName = "HasAccepted" States = @("No", "Yes") StateValues = @(0, 1) OnValue = 0 Type = "DWORD" CreatePathIfAbsent = $true }, # ── Input TIPC ──────────────────────────────────────────────────────────── @{ Group = "Input TIPC [User]" Label = "Typing Insights" Path = "HKCU:\Software\Microsoft\Input\TIPC" ValueName = "Enabled" States = @("Disabled", "Enabled") StateValues = @(0, 1) OnValue = 0 Type = "DWORD" }, # ── Input Personalisation ───────────────────────────────────────────────── @{ Group = "Input Personalisation [User]" Label = "Implicit Ink Collection" Path = "HKCU:\Software\Microsoft\InputPersonalization" ValueName = "RestrictImplicitInkCollection" States = @("Restricted", "Unrestricted") StateValues = @(1, 0) OnValue = 1 Type = "DWORD" }, @{ Group = "Input Personalisation [User]" Label = "Implicit Text Collection" Path = "HKCU:\Software\Microsoft\InputPersonalization" ValueName = "RestrictImplicitTextCollection" States = @("Restricted", "Unrestricted") StateValues = @(1, 0) OnValue = 1 Type = "DWORD" }, @{ Group = "Input Trained Data [User]" Label = "Harvest Contacts" Path = "HKCU:\Software\Microsoft\InputPersonalization\TrainedDataStore" ValueName = "HarvestContacts" States = @("Disabled", "Enabled") StateValues = @(0, 1) OnValue = 0 Type = "DWORD" }, # ── App Launch Tracking ─────────────────────────────────────────────────── @{ Group = "App Launch Tracking [User]" Label = "MFU Tracking" Path = "HKCU:\Software\Policies\Microsoft\Windows\EdgeUI" ValueName = "DisableMFUTracking" States = @("Disabled (tracking off)", "Enabled (tracking on)") StateValues = @(1, 0) OnValue = 1 Type = "DWORD" CreatePathIfAbsent = $true }, # ── Copilot User ────────────────────────────────────────────────────────── @{ Group = "Copilot [User]" Label = "Windows Copilot" Path = "HKCU:\Software\Policies\Microsoft\Windows\WindowsCopilot" ValueName = "TurnOffWindowsCopilot" States = @("Off", "On") StateValues = @(1, 0) OnValue = 1 Type = "DWORD" CreatePathIfAbsent = $true }, # ── System: Data Collection ─────────────────────────────────────────────── @{ Group = "Data Collection [System]" Label = "Telemetry (AllowTelemetry)" Path = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\DataCollection" ValueName = "AllowTelemetry" States = @("Disabled", "Enabled") StateValues = @(0, 1) OnValue = 0 Type = "DWORD" RequiresAdmin = $true }, # ── System: Copilot ─────────────────────────────────────────────────────── @{ Group = "Copilot [System]" Label = "Windows Copilot" Path = "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsCopilot" ValueName = "TurnOffWindowsCopilot" States = @("Off", "On") StateValues = @(1, 0) OnValue = 1 Type = "DWORD" RequiresAdmin = $true CreatePathIfAbsent = $true }, # ── System: App Launch Tracking ─────────────────────────────────────────── @{ Group = "App Launch Tracking [System]" Label = "MFU Tracking" Path = "HKLM:\Software\Policies\Microsoft\Windows\EdgeUI" ValueName = "DisableMFUTracking" States = @("Disabled (tracking off)", "Enabled (tracking on)") StateValues = @(1, 0) OnValue = 1 Type = "DWORD" RequiresAdmin = $true CreatePathIfAbsent = $true }, # ── System: Windows Search ──────────────────────────────────────────────── @{ Group = "Windows Search [System]" Label = "Allow Cortana" Path = "HKLM:\SOFTWARE\Policies\Microsoft\Windows\Windows Search" ValueName = "AllowCortana" States = @("No", "Yes") StateValues = @(0, 1) OnValue = 0 Type = "DWORD" RequiresAdmin = $true }, @{ Group = "Windows Search [System]" Label = "Cortana Consent" Path = "HKLM:\SOFTWARE\Policies\Microsoft\Windows\Windows Search" ValueName = "CortanaConsent" States = @("No", "Yes") StateValues = @(0, 1) OnValue = 0 Type = "DWORD" RequiresAdmin = $true } ) # ───────────────────────────────────────────────────────────────────────────── # REGION: Registry helpers # ───────────────────────────────────────────────────────────────────────────── function Test-RegistryPath { param([string]$Path) return (Test-Path -LiteralPath $Path) } function Get-SettingCurrentStateIndex { param($Setting) if (-not (Test-RegistryPath $Setting.Path)) { return -1 # path missing } try { $val = (Get-ItemProperty -LiteralPath $Setting.Path -Name $Setting.ValueName -ErrorAction Stop).$($Setting.ValueName) $idx = [Array]::IndexOf($Setting.StateValues, $val) if ($idx -lt 0) { return -1 } return $idx } catch { return -1 # value missing } } function Set-RegistrySetting { param($Setting, [int]$StateIndex) # Create the registry key if needed and allowed if (-not (Test-RegistryPath $Setting.Path)) { if ($Setting.CreatePathIfAbsent) { try { New-Item -Path $Setting.Path -Force | Out-Null } catch { return $false } } else { return $false } } try { Set-ItemProperty -LiteralPath $Setting.Path ` -Name $Setting.ValueName ` -Value $Setting.StateValues[$StateIndex] ` -Type $Setting.Type ` -ErrorAction Stop return $true } catch { return $false } } # ───────────────────────────────────────────────────────────────────────────── # REGION: TUI rendering # ───────────────────────────────────────────────────────────────────────────── $ColLabel = 0 $ColValue = 52 $ColStatus = 75 $TotalWidth = 90 function Write-Header { $title = " Windows Registry Settings Manager " $pad = [math]::Max(0, $TotalWidth - $title.Length) $left = [math]::Floor($pad / 2) $right = $pad - $left [Console]::SetCursorPosition(0, 0) Write-Host ("═" * $TotalWidth) -ForegroundColor DarkCyan Write-Host (("═" * $left) + $title + ("═" * $right)) -ForegroundColor Cyan Write-Host ("═" * $TotalWidth) -ForegroundColor DarkCyan Write-Host " ↑/↓ Navigate ←/→ Change value Q Quit R Reload" ` -ForegroundColor DarkGray Write-Host ("─" * $TotalWidth) -ForegroundColor DarkGray } function Write-Row { param( [int]$RowY, $Setting, [int]$StateIndex, [bool]$Selected, [string]$StatusMsg = "" ) [Console]::SetCursorPosition(0, $RowY) # Background for selected row $bgSel = if ($Selected) { [ConsoleColor]::DarkBlue } else { [ConsoleColor]::Black } $fgLabel = if ($Selected) { [ConsoleColor]::White } else { [ConsoleColor]::Gray } # Group badge colour cycling $groupColors = @([ConsoleColor]::DarkMagenta, [ConsoleColor]::DarkCyan, [ConsoleColor]::DarkYellow, [ConsoleColor]::DarkGreen, [ConsoleColor]::DarkRed, [ConsoleColor]::Blue) $groupHash = [Math]::Abs($Setting.Group.GetHashCode()) % $groupColors.Count $fgGroup = $groupColors[$groupHash] # Prefix $prefix = if ($Selected) { "▶ " } else { " " } # Build the label column (truncated to ColValue) $label = $prefix + $Setting.Label if ($label.Length -gt ($ColValue - 2)) { $label = $label.Substring(0, $ColValue - 5) + "..." } $label = $label.PadRight($ColValue - 2) # Value display if ($StateIndex -lt 0) { $valueStr = "(missing)".PadRight($ColStatus - $ColValue - 1) $fgValue = [ConsoleColor]::DarkRed } else { $v = $Setting.States[$StateIndex] $valueStr = $v.PadRight($ColStatus - $ColValue - 1) # Colour logic: index 0 is typically the "good/disabled/off" state $fgValue = if ($StateIndex -eq 0) { [ConsoleColor]::Green } else { [ConsoleColor]::Yellow } } # Status message (applied / error / admin etc.) $statusStr = $StatusMsg.PadRight($TotalWidth - $ColStatus) # Write the row Write-Host $label -NoNewline -ForegroundColor $fgLabel -BackgroundColor $bgSel Write-Host " " -NoNewline -BackgroundColor $bgSel Write-Host $valueStr -NoNewline -ForegroundColor $fgValue -BackgroundColor $bgSel Write-Host $statusStr -ForegroundColor DarkGray -BackgroundColor Black } function Write-GroupHeader { param([int]$RowY, [string]$GroupName) [Console]::SetCursorPosition(0, $RowY) $line = " ── $GroupName " + ("─" * [math]::Max(0, $TotalWidth - $GroupName.Length - 6)) Write-Host $line -ForegroundColor DarkCyan } function Write-Footer { param([int]$Y, [string]$Message = "") [Console]::SetCursorPosition(0, $Y) $line = (" " * $TotalWidth) Write-Host $line -NoNewline [Console]::SetCursorPosition(0, $Y) Write-Host " $Message" -ForegroundColor DarkGray } # ───────────────────────────────────────────────────────────────────────────── # REGION: Build the display list (interleave group headers + setting rows) # ───────────────────────────────────────────────────────────────────────────── # Assign state indices and build a flat list of "rows" for rendering # Each row is either type=Header or type=Setting $DisplayRows = [System.Collections.Generic.List[hashtable]]::new() $StatusMessages = @{} # index → message string $lastGroup = "" $settingIdx = 0 foreach ($s in $Settings) { if ($s.Group -ne $lastGroup) { $DisplayRows.Add(@{ RowType = "Header"; Group = $s.Group }) $lastGroup = $s.Group } $stateIdx = Get-SettingCurrentStateIndex $s $DisplayRows.Add(@{ RowType = "Setting" Setting = $s StateIndex = $stateIdx DataIndex = $settingIdx # index back into $Settings }) $settingIdx++ } # Build a parallel list of only the "Setting" rows for navigation $NavRows = $DisplayRows | Where-Object { $_.RowType -eq "Setting" } $navCount = @($NavRows).Count # ───────────────────────────────────────────────────────────────────────────── # REGION: Scrolling / viewport # ───────────────────────────────────────────────────────────────────────────── $HeaderLines = 5 # lines used by Write-Header $FooterLines = 4 # lines at bottom for status + path (path may wrap) $ViewportH = [Console]::WindowHeight - $HeaderLines - $FooterLines - 1 $ViewportH = [math]::Max(5, $ViewportH) $selectedNav = 0 # index in $NavRows $scrollOffset = 0 # first display-row index that is visible function Get-DisplayIndexForNav { param([int]$NavIdx) $target = $NavRows[$NavIdx] for ($i = 0; $i -lt $DisplayRows.Count; $i++) { if ($DisplayRows[$i] -eq $target) { return $i } } return 0 } function Ensure-Selected-Visible { $dispIdx = Get-DisplayIndexForNav $selectedNav if ($dispIdx -lt $scrollOffset) { $script:scrollOffset = $dispIdx } elseif ($dispIdx -ge ($scrollOffset + $ViewportH)) { $script:scrollOffset = $dispIdx - $ViewportH + 1 } } # ───────────────────────────────────────────────────────────────────────────── # REGION: Full redraw # ───────────────────────────────────────────────────────────────────────────── function Draw-Screen { param([string]$FooterMsg = "") [Console]::CursorVisible = $false Write-Header $screenY = $HeaderLines # Render visible display rows $visibleEnd = [math]::Min($DisplayRows.Count, $scrollOffset + $ViewportH) for ($di = $scrollOffset; $di -lt $visibleEnd; $di++) { $row = $DisplayRows[$di] if ($row.RowType -eq "Header") { Write-GroupHeader -RowY $screenY -GroupName $row.Group } else { $isSelected = ($row -eq $NavRows[$selectedNav]) $msg = if ($StatusMessages.ContainsKey($di)) { $StatusMessages[$di] } else { "" } Write-Row -RowY $screenY ` -Setting $row.Setting ` -StateIndex $row.StateIndex ` -Selected $isSelected ` -StatusMsg $msg } $screenY++ } # Clear any leftover lines below the rendered rows $blankLine = " " * $TotalWidth while ($screenY -lt ($HeaderLines + $ViewportH)) { [Console]::SetCursorPosition(0, $screenY) Write-Host $blankLine $screenY++ } # Scroll indicator [Console]::SetCursorPosition(0, $HeaderLines + $ViewportH) $scrollInfo = " Showing rows $($scrollOffset + 1)–$visibleEnd of $($DisplayRows.Count) ($navCount settings total)" Write-Host $scrollInfo.PadRight($TotalWidth) -ForegroundColor DarkGray # Registry path for the currently selected setting (wraps if too long) $selSetting = $NavRows[$selectedNav].Setting $pathFull = " 📂 " + $selSetting.Path + " › " + $selSetting.ValueName $pathContinue = " " $pathLines = [System.Collections.Generic.List[string]]::new() $remaining = $pathFull while ($remaining.Length -gt 0) { if ($remaining.Length -le $TotalWidth) { $pathLines.Add($remaining.PadRight($TotalWidth)) $remaining = "" } else { $breakAt = $TotalWidth for ($ci = $TotalWidth - 1; $ci -gt 20; $ci--) { if ($remaining[$ci] -eq '\' -or $remaining[$ci] -eq ' ') { $breakAt = $ci + 1 break } } $pathLines.Add($remaining.Substring(0, $breakAt).PadRight($TotalWidth)) $remaining = $pathContinue + $remaining.Substring($breakAt).TrimStart('\') } } # Render up to 2 path lines $pathRender = @($pathLines | Select-Object -First 2) for ($pi = 0; $pi -lt $pathRender.Count; $pi++) { [Console]::SetCursorPosition(0, $HeaderLines + $ViewportH + 1 + $pi) Write-Host $pathRender[$pi] -ForegroundColor DarkGray } # Clear unused second line so no stale text lingers if ($pathRender.Count -lt 2) { [Console]::SetCursorPosition(0, $HeaderLines + $ViewportH + 2) Write-Host (" " * $TotalWidth) } # Footer message (always on the last reserved line) [Console]::SetCursorPosition(0, $HeaderLines + $ViewportH + 3) Write-Host (" " + $FooterMsg).PadRight($TotalWidth) -ForegroundColor DarkYellow } # ───────────────────────────────────────────────────────────────────────────── # REGION: Apply a change # ───────────────────────────────────────────────────────────────────────────── function Apply-Change { param([int]$NavIdx, [int]$Direction) # Direction: +1 or -1 $row = $NavRows[$NavIdx] $s = $row.Setting # Find display index for status message storage $dispIdx = Get-DisplayIndexForNav $NavIdx # Current state index $cur = $row.StateIndex if ($cur -lt 0) { $cur = 0 } # if missing, start from 0 $count = $s.States.Count $newIdx = (($cur + $Direction) % $count + $count) % $count $ok = Set-RegistrySetting -Setting $s -StateIndex $newIdx if ($ok) { $row.StateIndex = $newIdx $StatusMessages[$dispIdx] = "✔ Applied" return "✔ Applied: $($s.Label) → $($s.States[$newIdx])" } else { $hint = if ($s.RequiresAdmin) { " (needs admin)" } else { "" } $StatusMessages[$dispIdx] = "✘ Failed$hint" return "✘ Failed to apply: $($s.Label)$hint" } } # ───────────────────────────────────────────────────────────────────────────── # REGION: Main loop # ───────────────────────────────────────────────────────────────────────────── # Set up console $origTitle = [Console]::Title [Console]::Title = "Windows Registry Settings Manager" [Console]::CursorVisible = $false [Console]::TreatControlCAsInput = $true Clear-Host $footerMsg = "Ready. Use arrow keys to navigate and change settings." Ensure-Selected-Visible Draw-Screen -FooterMsg $footerMsg try { while ($true) { if ([Console]::KeyAvailable) { $key = [Console]::ReadKey($true) switch ($key.Key) { "UpArrow" { if ($selectedNav -gt 0) { $selectedNav-- Ensure-Selected-Visible Draw-Screen -FooterMsg $footerMsg } } "DownArrow" { if ($selectedNav -lt ($navCount - 1)) { $selectedNav++ Ensure-Selected-Visible Draw-Screen -FooterMsg $footerMsg } } "LeftArrow" { $footerMsg = Apply-Change -NavIdx $selectedNav -Direction -1 Draw-Screen -FooterMsg $footerMsg } "RightArrow" { $footerMsg = Apply-Change -NavIdx $selectedNav -Direction 1 Draw-Screen -FooterMsg $footerMsg } "PageUp" { $selectedNav = [math]::Max(0, $selectedNav - 10) Ensure-Selected-Visible Draw-Screen -FooterMsg $footerMsg } "PageDown" { $selectedNav = [math]::Min($navCount - 1, $selectedNav + 10) Ensure-Selected-Visible Draw-Screen -FooterMsg $footerMsg } "Home" { $selectedNav = 0 Ensure-Selected-Visible Draw-Screen -FooterMsg $footerMsg } "End" { $selectedNav = $navCount - 1 Ensure-Selected-Visible Draw-Screen -FooterMsg $footerMsg } "R" { # Reload all values from registry $StatusMessages.Clear() $settingIdx2 = 0 foreach ($dr in $DisplayRows) { if ($dr.RowType -eq "Setting") { $dr.StateIndex = Get-SettingCurrentStateIndex $dr.Setting $settingIdx2++ } } $footerMsg = "All values reloaded from registry." Draw-Screen -FooterMsg $footerMsg } "Q" { break } { $key.KeyChar -eq 'q' -or $key.KeyChar -eq 'Q' } { break } } if ($key.Key -eq "Q" -or $key.KeyChar -eq 'q' -or $key.KeyChar -eq 'Q') { break } # Ctrl+C if ($key.Key -eq "C" -and ($key.Modifiers -band [ConsoleModifiers]::Control)) { break } } Start-Sleep -Milliseconds 30 } } finally { [Console]::CursorVisible = $true [Console]::TreatControlCAsInput = $false [Console]::Title = $origTitle Clear-Host Write-Host "Windows Registry Settings Manager closed." -ForegroundColor Cyan }