<# .SYNOPSIS Switches a Windows device to a built-in power plan, creating it first if it's hidden. .DESCRIPTION Works with the plans by GUID rather than by name, so it behaves the same on every language of Windows. If the plan you ask for isn't on the machine (Ultimate Performance is hidden by default, and some OEM images drop High Performance), -CreateIfMissing copies it from the built-in template under a fixed GUID, so running the script twice doesn't leave you with two copies. .PARAMETER Plan Balanced, HighPerformance, UltimatePerformance or PowerSaver. .PARAMETER CreateIfMissing Restore the plan from its built-in template if it isn't listed. .PARAMETER StandbyTimeoutAC Optional. Minutes before sleep when plugged in, applied to the chosen plan. 0 means never. .EXAMPLE .\Set-PowerPlan.ps1 -Plan HighPerformance -WhatIf .EXAMPLE .\Set-PowerPlan.ps1 -Plan UltimatePerformance -CreateIfMissing -StandbyTimeoutAC 0 #> [CmdletBinding(SupportsShouldProcess)] param( [Parameter(Mandatory)] [ValidateSet('Balanced', 'HighPerformance', 'UltimatePerformance', 'PowerSaver')] [string]$Plan, [switch]$CreateIfMissing, [ValidateRange(0, 600)] [int]$StandbyTimeoutAC = -1 ) # Built-in template GUIDs, plus the fixed GUID we use if we have to restore a copy. $plans = @{ Balanced = @{ Template = '381b4222-f694-41f0-9685-ff5bb260df2e'; Copy = '0d8f2a6c-4e1b-4c79-a3d5-8b6e2f9c1a07' } HighPerformance = @{ Template = '8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c'; Copy = '3f1c8b2e-7a64-4d0f-9b3e-6c2a1d8e5f47' } UltimatePerformance = @{ Template = 'e9a42b02-d5df-448d-aa00-03f14749eb61'; Copy = '5b1a7c3e-9d42-4f6e-8a1b-2c7d9e0f4a61' } PowerSaver = @{ Template = 'a1841308-3541-4fab-bc81-f71556f20b4a'; Copy = 'c7e4a9d1-2b58-4e3a-8f06-1d9b7c3a2e84' } } $guidPattern = '[0-9a-fA-F]{8}-(?:[0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12}' function Get-PowerSchemes { foreach ($line in @(powercfg /list)) { if ($line -match "($guidPattern)\s+\((.+?)\)") { [pscustomobject]@{ Guid = $Matches[1].ToLower(); Name = $Matches[2]; Active = $line.TrimEnd().EndsWith('*') } } } } $schemes = @(Get-PowerSchemes) $previous = $schemes | Where-Object Active | Select-Object -First 1 $wanted = $plans[$Plan] $target = $schemes | Where-Object { $_.Guid -in $wanted.Template, $wanted.Copy } | Select-Object -First 1 $action = 'NoChange' if (-not $target) { if (-not $CreateIfMissing) { Write-Error "The $Plan plan isn't available on this device. Run again with -CreateIfMissing to restore it." exit 1 } if ($PSCmdlet.ShouldProcess($env:COMPUTERNAME, "Restore $Plan plan as $($wanted.Copy)")) { $null = powercfg /duplicatescheme $wanted.Template $wanted.Copy if ($LASTEXITCODE -ne 0) { Write-Error "powercfg couldn't restore the $Plan plan (exit $LASTEXITCODE)."; exit 1 } $target = [pscustomobject]@{ Guid = $wanted.Copy; Name = $Plan; Active = $false } $action = 'Created' } else { $target = [pscustomobject]@{ Guid = $wanted.Copy; Name = $Plan; Active = $false }; $action = 'WhatIf' } } if (-not $target.Active -and $action -ne 'WhatIf') { if ($PSCmdlet.ShouldProcess($env:COMPUTERNAME, "Activate $($target.Name) ($($target.Guid))")) { powercfg /setactive $target.Guid if ($LASTEXITCODE -ne 0) { Write-Error "powercfg /setactive failed (exit $LASTEXITCODE)."; exit 1 } $action = if ($action -eq 'Created') { 'CreatedAndActivated' } else { 'Activated' } } else { $action = 'WhatIf' } } if ($StandbyTimeoutAC -ge 0 -and $action -ne 'WhatIf') { # SUB_SLEEP / STANDBYIDLE takes seconds; set it on the target plan, not whatever happens to be active. if ($PSCmdlet.ShouldProcess($target.Name, "Set AC sleep timeout to $StandbyTimeoutAC minute(s)")) { powercfg /setacvalueindex $target.Guid SUB_SLEEP STANDBYIDLE ($StandbyTimeoutAC * 60) powercfg /setactive $target.Guid } } $active = Get-PowerSchemes | Where-Object Active | Select-Object -First 1 [pscustomobject]@{ ComputerName = $env:COMPUTERNAME Requested = $Plan Previous = if ($previous) { $previous.Name } else { $null } Active = if ($active) { $active.Name } else { $null } ActiveGuid = if ($active) { $active.Guid } else { $null } Action = $action }