SCRIPT LIBRARY · POWERSHELL
Setting a High Performance Power Plan with an SCCM Package
Switch workstations to High Performance (or Ultimate Performance) by GUID, restore the plan if the image hid it, and don't end up with five copies of it.
- What it does
- Activates a built-in Windows power plan by GUID, restores it from the built-in template if it's missing, and can set the plugged-in sleep timeout on it. Returns what was active before and after.
- Requires
- Windows PowerShell 5.1 (PowerShell 7 works too)
- powercfg.exe (built in)
- Permissions
- Local administrator or SYSTEM to change the active plan for the machine.
- Runs on
- Windows 10/11, Windows Server 2016+
- Tested
- Parse-checked and dry-run with a mocked powercfg in PowerShell 7.4, including repeat runs
Part 3 of the thread Packaging with ConfigMgr
Some machines have no business going to sleep or parking CPU cores: the CAD workstation, the box that renders overnight, the kiosk that has to be awake when someone walks up to it. For those, High Performance is the plan you want, and setting it by hand on each one gets old fast.
The old version of this post ran powercfg -setactive SCHEME_MIN. That's actually right, if confusing: SCHEME_MIN means "minimum power saving," which is High Performance. But it fell over on any machine where the plan had been hidden, and it couldn't do Ultimate Performance at all, since that one is hidden on almost every edition of Windows.
This version works by GUID, so it doesn't care what language Windows is in. It can restore a missing plan from the built-in template, and it restores it under a fixed GUID, so running it every day doesn't leave you with a list of identical plans in Control Panel.
<#
.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
}
Parameters
| Parameter | Type | Default | What it's for |
|---|---|---|---|
-Plan | string | — | Required. Balanced, HighPerformance, UltimatePerformance or PowerSaver. |
-CreateIfMissing | switch | — | If the plan isn't listed on the machine, restore it from the built-in template before activating it. |
-StandbyTimeoutAC | int | -1 | Minutes before sleep when plugged in, set on the chosen plan. 0 means never. Leave it off to keep the plan's own setting. |
Run it
Preview the switch to High Performance.
.\Set-PowerPlan.ps1 -Plan HighPerformance -WhatIfHigh Performance, and never sleep while plugged in.
.\Set-PowerPlan.ps1 -Plan HighPerformance -CreateIfMissing -StandbyTimeoutAC 0Ultimate Performance for a render box. It's hidden by default, so restore it.
.\Set-PowerPlan.ps1 -Plan UltimatePerformance -CreateIfMissingAs a ConfigMgr program command line.
powershell.exe -NoProfile -ExecutionPolicy Bypass -File .\Set-PowerPlan.ps1 -Plan HighPerformance -CreateIfMissingWhat you'll see
ComputerName : PC-0142
Requested : HighPerformance
Previous : Balanced
Active : High performance
ActiveGuid : 8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c
Action : Activated
How it works
- List what's there. It runs
powercfg /listand pulls out each plan's GUID, name, and whether it's the active one (the line ending in*). Only the GUID and the layout are relied on, not the wording. - Find the plan you asked for. It looks for either the built-in GUID or the fixed GUID the script uses for a restored copy. Either one counts.
- Restore it if needed. With
-CreateIfMissing, it runspowercfg /duplicatescheme <template> <fixed GUID>. Passing the destination GUID is the important part. Without it, powercfg invents a new GUID every time, and a daily deployment slowly fills Control Panel with copies. - Activate it.
powercfg /setactivewith the GUID, then a check of the exit code, so a failure is reported as a failure and not as a mystery. - Optional sleep timeout.
-StandbyTimeoutACsets the plugged-in sleep value on that plan with/setacvalueindex, in seconds, and re-applies the plan so it takes effect now. - Report. You get the previous plan, the active plan and what the script did:
NoChange,Activated,Created,CreatedAndActivatedorWhatIf.
For deployment, a package with a program is fine for a one-time switch. If you want machines to stay on the plan, make it a configuration item: a tiny discovery script that compares powercfg /getactivescheme against the GUID, and this script as the remediation.
Take it further
- Report before you change.
powercfg /getactiveschemein a Run Scripts job across a collection shows you who's on what before you touch anything. - Tune the plan, not just the choice.
powercfg /setacvalueindexcan set disk, USB selective suspend and processor minimum state the same way the script sets sleep. - Export a golden plan. Tune one machine,
powercfg /exportthe plan, and/importit with a fixed GUID everywhere else.
Things that'll trip you up
- Modern Standby laptops only really do Balanced. On devices that use Modern Standby, Windows shows only the Balanced plan and uses the power mode slider on top of it. You can force a restored plan onto one, but you're fighting the platform. Leave those on Balanced and set the slider instead.
- A script sets it; it doesn't keep it set. Anyone with admin rights can switch plans back. If it has to stay put, use the "Select an active power plan" Group Policy setting, or run this as a configuration item with remediation.
- Battery life goes with it. High Performance applies on battery too. Fine for a desktop, rough on a laptop that leaves the desk. Target a collection of desktops, not "All Workstations."
- Plan names are translated, GUIDs aren't. That's why the script matches on GUIDs. If you adapt it, don't switch to matching "High performance" by name, or it breaks the first time it meets a German install.