<# .SYNOPSIS Switch the RetroBar theme (or any other RetroBar setting) from the command line. .DESCRIPTION RetroBar has no command-line options (RetroBar issue #958). It reads its settings from %LOCALAPPDATA%\RetroBar\settings.json when it starts. This script closes RetroBar, changes the values you ask for in settings.json, and starts RetroBar again. Published by retrobar.dev (not part of the RetroBar project). Tested on Windows with RetroBar 1.22.122; see https://retrobar.dev/tools/settings-builder/ .EXAMPLE .\Set-RetroBarTheme.ps1 -Theme 'Windows XP Blue' .EXAMPLE .\Set-RetroBarTheme.ps1 -List .EXAMPLE .\Set-RetroBarTheme.ps1 -Theme 'Windows 2000' -Set @{ ShowClockSeconds = $true; Edge = 1 } #> [CmdletBinding(DefaultParameterSetName = 'Apply')] param( [Parameter(ParameterSetName = 'Apply', Position = 0)][string]$Theme, [Parameter(ParameterSetName = 'Apply')][hashtable]$Set = @{}, [Parameter(ParameterSetName = 'List')][switch]$List, [string]$RetroBarPath ) $ErrorActionPreference = 'Stop' $dataDir = Join-Path $env:LOCALAPPDATA 'RetroBar' $settingsFile = Join-Path $dataDir 'settings.json' function Find-RetroBarExe { if ($RetroBarPath) { return (Resolve-Path $RetroBarPath).Path } $running = Get-Process RetroBar -ErrorAction SilentlyContinue | Select-Object -First 1 if ($running -and $running.Path) { return $running.Path } foreach ($hive in 'HKCU', 'HKLM') { $key = "${hive}:\Software\Microsoft\Windows\CurrentVersion\Uninstall\{574527FE-00A4-4F85-92AD-B4B8B4077D73}_is1" $loc = (Get-ItemProperty $key -ErrorAction SilentlyContinue).InstallLocation if ($loc -and (Test-Path (Join-Path $loc 'RetroBar.exe'))) { return (Join-Path $loc 'RetroBar.exe') } } foreach ($p in "$env:LOCALAPPDATA\Programs\RetroBar\RetroBar.exe", "$env:ProgramFiles\RetroBar\RetroBar.exe") { if (Test-Path $p) { return $p } } throw 'RetroBar.exe not found. Start RetroBar once, or pass -RetroBarPath "C:\path\to\RetroBar.exe".' } function Get-Themes($exe) { $dirs = @((Join-Path (Split-Path $exe) 'Themes'), (Join-Path $dataDir 'Themes')) $names = foreach ($d in $dirs) { if (Test-Path $d) { Get-ChildItem $d -Filter *.xaml | ForEach-Object { $_.BaseName } } } return @('System') + @($names | Where-Object { $_ -ne 'System' } | Sort-Object -Unique) } $exe = Find-RetroBarExe if ($List) { Get-Themes $exe; return } if ($Theme) { $themes = Get-Themes $exe $match = $themes | Where-Object { $_ -ieq $Theme } | Select-Object -First 1 if (-not $match) { throw "Unknown theme '$Theme'. Available: $($themes -join ', ')" } $Set['Theme'] = $match } if ($Set.Count -eq 0) { throw 'Nothing to change. Use -Theme and/or -Set @{ Name = value }.' } # Stop RetroBar first: it writes settings.json itself and would overwrite our change. # It has no command to quit from outside (asking its window to close does nothing; tested on # Windows 11 and Server 2025/2022), so the process is ended. It is started again below, and on # start it hides the Windows taskbar again. Get-Process RetroBar -ErrorAction SilentlyContinue | Stop-Process -Force Start-Sleep -Milliseconds 800 New-Item -ItemType Directory -Force -Path $dataDir | Out-Null $json = if (Test-Path $settingsFile) { Get-Content $settingsFile -Raw | ConvertFrom-Json } else { [pscustomobject]@{} } foreach ($k in $Set.Keys) { $json | Add-Member -NotePropertyName $k -NotePropertyValue $Set[$k] -Force } [IO.File]::WriteAllText($settingsFile, ($json | ConvertTo-Json -Depth 8), (New-Object Text.UTF8Encoding $false)) Start-Process -FilePath $exe -WorkingDirectory (Split-Path $exe) Write-Host ("RetroBar restarted with: " + (($Set.GetEnumerator() | ForEach-Object { "$($_.Key) = $($_.Value)" }) -join '; '))