Skip to main content

How to Create a Custom Power Plan in Batch Script

When deploying specialized kiosks, rendering workstations, or dedicated presentation displays, the default Windows power plans (Balanced, High Performance, Power Saver) are often inadequate. Furthermore, relying on users to manually configure their active power settings inevitably leads to inconsistencies and unexpected system sleep events.

In this guide, we will explore the proper way to programmatically create a custom power plan using the Windows powercfg command-line utility within a Batch Script.

Understanding the Process

Creating a power plan from scratch using powercfg is not actually a "create" operation; it is a duplicate operation.

Windows requires all new custom plans to be based on an existing foundational scheme. The typical workflow is:

  1. Duplicate an existing base plan (usually "Balanced").
  2. Capture the Globally Unique Identifier (GUID) of the newly created clone.
  3. Rename the new clone to your desired custom name.
  4. Modify the specific settings (timeouts, performance thresholds) on the new GUID.
  5. Set the new GUID as the active power scheme.

The Script: Creating an "Always On Kiosk" Plan

This script will take the standard "Balanced" plan, duplicate it, name it "Kiosk Mode", set it so the monitor and hard drive never sleep, and activate it.

@echo off
setlocal enabledelayedexpansion

echo Creating Custom "Kiosk Mode" Power Plan...
echo ==========================================

:: 1. Define the base plan to duplicate.
:: 381b4222-f694-41f0-9685-ff5bb260df2e is the universal GUID for "Balanced"
set "base_guid=381b4222-f694-41f0-9685-ff5bb260df2e"

:: 2. Duplicate the base plan and capture the new GUID
:: The output of duplicatescheme looks like:
:: Power Scheme GUID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx (Balanced)
set "new_guid="
for /f "tokens=*" %%A in ('powercfg /duplicatescheme %base_guid% 2^>nul') do (
set "line=%%A"
for /f "tokens=4" %%G in ("%%A") do (
set "candidate=%%G"
echo !candidate! | findstr /r "[0-9a-fA-F]*-[0-9a-fA-F]*-[0-9a-fA-F]*-[0-9a-fA-F]*-[0-9a-fA-F]*" >nul 2>&1
if !errorlevel! equ 0 set "new_guid=%%G"
)
)

if not defined new_guid (
echo [ERROR] Failed to duplicate the power scheme.
echo Ensure you are running this script as Administrator.
pause
exit /b 1
)

echo [OK] Base plan duplicated. New GUID: !new_guid!

:: 3. Rename the newly created plan and provide a description
powercfg /changename !new_guid! "Kiosk Mode" "Optimized for continuous, 24/7 unmonitored display."
echo [OK] Renamed to "Kiosk Mode".

:: 4. Customize the settings of the new plan (0 = Never)
:: Monitor Timeout (seconds on AC and DC)
powercfg /setacvalueindex !new_guid! SUB_VIDEO VIDEOIDLE 0
powercfg /setdcvalueindex !new_guid! SUB_VIDEO VIDEOIDLE 0

:: Sleep Timeout
powercfg /setacvalueindex !new_guid! SUB_SLEEP STANDBYIDLE 0
powercfg /setdcvalueindex !new_guid! SUB_SLEEP STANDBYIDLE 0

:: Hard Disk Spindown Timeout
powercfg /setacvalueindex !new_guid! SUB_DISK DISKIDLE 0
powercfg /setdcvalueindex !new_guid! SUB_DISK DISKIDLE 0

:: Hibernate Timeout
powercfg /setacvalueindex !new_guid! SUB_SLEEP HIBERNATEIDLE 0
powercfg /setdcvalueindex !new_guid! SUB_SLEEP HIBERNATEIDLE 0

echo [OK] Settings customized.

:: 5. Activate the new plan
powercfg /setactive !new_guid!

echo.
echo [SUCCESS] "Kiosk Mode" power plan is now active!
echo GUID: !new_guid!
pause

Explaining the Customization Commands

Notice that we used powercfg /setacvalueindex instead of powercfg /change.

While powercfg /change monitor-timeout-ac 0 works, it always modifies the currently active plan. Because our script hasn't activated our new "Kiosk Mode" plan yet (we want to fully build it before activating), we must target the specific !new_guid! using the index method.

info

The setting alias names used with /setacvalueindex and /setdcvalueindex are case-insensitive but must match the actual Windows power setting identifiers:

  • SUB_VIDEO / VIDEOIDLE: The subgroup and setting controlling the monitor turn-off timeout.
  • SUB_SLEEP / STANDBYIDLE: The subgroup and setting controlling system sleep (standby).
  • SUB_SLEEP / HIBERNATEIDLE: The setting controlling hibernate timeout within the sleep subgroup.
  • SUB_DISK / DISKIDLE: The subgroup and setting managing hard drive spin-down.

You can discover all available subgroup and setting aliases on your system by running powercfg /query.

Advanced: Updating an Existing Custom Plan

A common problem with deployment scripts is that if you run them twice, you create two separate "Kiosk Mode" plans with different GUIDs. To avoid cluttering the system, your script should first check if the custom plan already exists before creating a new one.

@echo off
setlocal enabledelayedexpansion

set "plan_name=Automated Render Profile"
set "base_guid=8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c"
set "found_guid="

echo Checking if "%plan_name%" already exists...

:: Search the list of installed plans for the exact name
for /f "tokens=*" %%L in ('powercfg /list 2^>nul') do (
set "line=%%L"

:: Extract the GUID (token 4 from the line)
set "guid="
for /f "tokens=4" %%G in ("%%L") do set "guid=%%G"

:: Extract the plan name from between parentheses
set "name="
for /f "tokens=1 delims=()" %%N in ("!line:*^(=!") do (
rem The line after the opening paren up to closing paren
)
:: Use a simpler approach: check if the line contains the plan name
echo !line! | findstr /c:"(!plan_name!)" >nul 2>&1
if !errorlevel! equ 0 (
if defined guid (
set "found_guid=!guid!"
echo [OK] Found existing plan: !found_guid!
goto :plan_ready
)
)
)

:plan_create
echo Plan not found. Creating new copy from High Performance...
set "found_guid="
for /f "tokens=*" %%A in ('powercfg /duplicatescheme %base_guid% 2^>nul') do (
for /f "tokens=4" %%G in ("%%A") do (
set "candidate=%%G"
echo !candidate! | findstr /r "[0-9a-fA-F]*-[0-9a-fA-F]*-[0-9a-fA-F]*-[0-9a-fA-F]*-[0-9a-fA-F]*" >nul 2>&1
if !errorlevel! equ 0 set "found_guid=%%G"
)
)

if not defined found_guid (
echo [ERROR] Failed to duplicate the power scheme.
echo Ensure you are running this script as Administrator.
pause
exit /b 1
)

powercfg /changename !found_guid! "%plan_name%" "Maximum performance for 3D rendering."
echo [OK] Plan created: !found_guid!

:plan_ready
echo.
echo Proceeding with GUID: !found_guid!
echo Customizing settings...

:: Disable all sleep and display timeouts
powercfg /setacvalueindex !found_guid! SUB_VIDEO VIDEOIDLE 0
powercfg /setdcvalueindex !found_guid! SUB_VIDEO VIDEOIDLE 0
powercfg /setacvalueindex !found_guid! SUB_SLEEP STANDBYIDLE 0
powercfg /setdcvalueindex !found_guid! SUB_SLEEP STANDBYIDLE 0
powercfg /setacvalueindex !found_guid! SUB_DISK DISKIDLE 0
powercfg /setdcvalueindex !found_guid! SUB_DISK DISKIDLE 0

:: Set CPU minimum processor state to 100% on AC power
powercfg /setacvalueindex !found_guid! SUB_PROCESSOR PROCTHROTTLEMIN 100

:: Set system cooling policy to Active (1) on AC power
powercfg /setacvalueindex !found_guid! SUB_PROCESSOR SYSCOOLPOL 1

:: Activate the plan
powercfg /setactive !found_guid!
echo [SUCCESS] "%plan_name%" activated.
pause

Why We Duplicate High Performance Here

In the second example, our base GUID was 8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c, the standard Windows "High Performance" plan. When creating a rendering profile, duplicating High Performance ensures that hundreds of hidden sub-settings (like PCIe Link State Power Management and CPU Minimum State) default to maximum power without needing to manually script every single subgroup.

tip

You can verify which base plans are available on a system by running powercfg /list. The three standard GUIDs are:

PlanGUID
Power Savera1841308-3541-4fab-bc81-f71556f20b4a
Balanced381b4222-f694-41f0-9685-ff5bb260df2e
High Performance8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c

Some editions of Windows 10/11 also include an "Ultimate Performance" plan (e9a42b02-d5df-448d-aa00-03f14749eb61), but it is not present on all systems by default.

Common Mistakes

The Wrong Way: Trying to Create a Plan from Thin Air

:: WRONG - powercfg has no "create" command
powercfg /create "My Plan"
danger

The command will fail with an "Invalid parameters" error. You must use /duplicatescheme <BaseGUID>, capture the resulting clone GUID, and then rename the clone.

The Correct Way: Duplicate and Rename

:: CORRECT - Copy an existing plan, then rename the copy
for /f "tokens=4" %%G in ('powercfg /duplicatescheme 381b4222-f694-41f0-9685-ff5bb260df2e') do set "new_guid=%%G"
powercfg /changename %new_guid% "My Custom Plan" "Description of this plan."

The Wrong Way: Using /change Instead of /setacvalueindex

:: WRONG - If your script hasn't activated the new plan yet, this edits the ORIGINAL active plan
powercfg /change monitor-timeout-ac 0
warning

Always use /setacvalueindex targeting your parsed !new_guid! to ensure you are only modifying the custom plan you just generated, leaving the system defaults untouched. The /change shorthand always operates on whichever plan is currently active at the moment the command runs.

The Wrong Way: Using Incorrect Setting Alias Names

:: WRONG - These are not valid powercfg setting aliases
powercfg /setacvalueindex %guid% SUB_VIDEO VideoDim 0
powercfg /setacvalueindex %guid% SUB_SLEEP StandbyIdle 0
powercfg /setacvalueindex %guid% SUB_DISK DiskIdle 0
danger

While these alias names look plausible, they do not match the actual internal identifiers that powercfg recognizes. Using incorrect aliases causes the command to fail silently or return an error. The correct aliases are VIDEOIDLE, STANDBYIDLE, and DISKIDLE respectively. Always verify aliases against powercfg /query output on your target system.

Best Practices

  1. Always duplicate, never assume creation: Windows power plans must originate from an existing scheme via /duplicatescheme.
  2. Validate the captured GUID: After duplication, confirm that the parsed GUID variable is defined and resembles a valid GUID pattern before proceeding.
  3. Use /setacvalueindex and /setdcvalueindex: Target settings by GUID to avoid accidentally modifying the wrong plan.
  4. Check for existing plans before duplicating: Prevent accumulating duplicate custom plans on repeated script runs by searching powercfg /list output first.
  5. Run as Administrator: Power plan creation and modification require elevated privileges. Include a check or clear error message if the script is run without elevation.
  6. Verify setting aliases: Use powercfg /query to confirm the correct subgroup and setting alias names for your target Windows version.

Conclusion

Creating custom power plans through Batch Scripting is a powerful method for standardizing environments across multiple machines. By duplicating specific foundational schemes (like Balanced or High Performance), retrieving the dynamically generated GUID via a for /f parsing loop, and renaming the clone structure, administrators avoid cluttering user machines with poorly configured environments. Incorporating a check to see if the plan already exists prior to duplication cements the script as a professional, idempotent deployment utility.