How do I force a python script to run in efficiency mode so the green leaf appears next to its' listing in TaskManager?

Matt_the_ok 0 Reputation points
2025-02-08T01:30:45.95+00:00

Hi all, as the title states, I'm looking to make a python script run in efficiency mode and it has to show the leaf in TaskManager so psutils is out (right?).

I'm running cmd as administrator and I've tried using ctypes to throttle the power through SetProcessInformation() but it keeps yelling Error 87 (Invalid Parameter) at me. Here's me code:

import time
import ctypes
import os

# Define constants
PROCESS_POWER_THROTTLING_EXECUTION_SPEED = 0x1
PROCESS_INFORMATION_CLASS = 0x1F

# Define the POWER_THROTTLING_STATE structure
class POWER_THROTTLING_STATE(ctypes.Structure):
    _fields_ = [
        ("Version", ctypes.c_ulong),
        ("ControlMask", ctypes.c_ulong),
        ("StateMask", ctypes.c_ulong),
    ]

# Get the current process handle
current_process = ctypes.windll.kernel32.GetCurrentProcess()

# Set up the POWER_THROTTLING_STATE structure
power_throttling_state = POWER_THROTTLING_STATE()
power_throttling_state.Version = 1
power_throttling_state.ControlMask = PROCESS_POWER_THROTTLING_EXECUTION_SPEED
power_throttling_state.StateMask = PROCESS_POWER_THROTTLING_EXECUTION_SPEED

# Call SetProcessInformation to enable Efficiency Mode
result = ctypes.windll.kernel32.SetProcessInformation(
    current_process,
    PROCESS_INFORMATION_CLASS,
    ctypes.byref(power_throttling_state),
    ctypes.sizeof(power_throttling_state),
)

if result:
    print("Efficiency Mode enabled for this script. The green leaf should appear in Task Manager.")
else:
    # Get the last error code
    error_code = ctypes.windll.kernel32.GetLastError()
    print(f"Failed to enable Efficiency Mode. Error code: {error_code}")
    # Common error codes and their meanings
    if error_code == 5:
        print("Error 5: Access Denied. Ensure you're running the script as Administrator.")
    elif error_code == 87:
        print("Error 87: Invalid Parameter. Check the parameters passed to SetProcessInformation.")
    else:
        print("Unknown error. Check your Windows version and permissions.")

time.sleep(10)

Any thoughts?

Thanks,

Matt-the-ok

Windows API - Win32
Windows API - Win32
A core set of Windows application programming interfaces (APIs) for desktop and server applications. Previously known as Win32 API.
2,735 questions
{count} votes

1 answer

Sort by: Most helpful
  1. Matt_the_ok 0 Reputation points
    2025-02-19T18:09:15.4566667+00:00

    Hi all,

    Firstly, thanks for the help, you definitely helped me move forward, particularly this bit:
    ProcessPowerThrottling (4)

    However, even with that it still wasn't working. I ended up printing process information through Powershell and noticed the BasePriority wasn't matching up using my script versus manually setting in efficiency mode through the Task Manager. Once I set the BasePriority to IDLE_PRIORITY_CLASS (0x00000040), the green leaf indicating efficiency mode appeared. Here's the final bit of code:

    # Define the PROCESS_pPState structure
    class PROCESS_pPState(ctypes.Structure):
        _fields_ = [
            ('Version',     wintypes.ULONG),
            ('ControlMask', wintypes.ULONG),
            ('StateMask',   wintypes.ULONG)
        ]
    
    def enable_on_eco_mode():
        # Constants from the Windows API
        PROCESS_POWER_THROTTLING_EXECUTION_SPEED = 0x1
        PROCESS_POWER_THROTTLING_CURRENT_VERSION = 1
        ProcessPowerThrottling = 4
        PROCESS_QUERY_INFORMATION = 0x0400
        PROCESS_SET_INFORMATION = 0x0200
        IDLE_PRIORITY_CLASS = 0x00000040 # Base Priority 4
    
        kernel32 = ctypes.WinDLL("kernel32", use_last_error=True)
        pid = kernel32.GetCurrentProcessId()
    
        pPState = PROCESS_pPState()
        pPState.Version = PROCESS_POWER_THROTTLING_CURRENT_VERSION
        pPState.ControlMask = PROCESS_POWER_THROTTLING_EXECUTION_SPEED
        pPState.StateMask = PROCESS_POWER_THROTTLING_EXECUTION_SPEED
    
        # Setup the necessary functions from Windows API
        GetLastError = windll.kernel32.GetLastError
    
        SetPriorityClass = kernel32.SetPriorityClass
    
        SetProcessInformation = windll.kernel32.SetProcessInformation
        SetProcessInformation.argtypes = (
            wintypes.HANDLE,
            wintypes.DWORD,
            wintypes.LPVOID,
            wintypes.DWORD,
        )
        SetProcessInformation.restype = wintypes.BOOL
    
        OpenProcess = windll.kernel32.OpenProcess
        OpenProcess.argtypes = (
            wintypes.DWORD,
            wintypes.BOOL,
            wintypes.DWORD,
        )
        OpenProcess.restype = wintypes.HANDLE
    
        # Get the current process handle
        hProcess = OpenProcess(
            PROCESS_QUERY_INFORMATION | PROCESS_SET_INFORMATION,
            False,  # Don't inherit the handle
            pid
        )
        if hProcess == 0:
            raise Exception(f'could not open process pid {pid} error={GetLastError()}')
    
        # Change the BasePriority in Windows from 8 (NORMAL_PRIORITY_CLASS) to 4 (IDLE_PRIORITY_CLASS)
        result = SetPriorityClass(hProcess, IDLE_PRIORITY_CLASS)
    
        if not result:
            # Get the last error code
            error_code = GetLastError()
            print(f"SetPriorityClass failed to lower priority. Error code: {error_code}")
    
        # Set the process information to enable Efficiency Mode
        result = SetProcessInformation(
            hProcess,
            ProcessPowerThrottling,
            ctypes.byref(pPState),
            ctypes.sizeof(pPState),
        )
    
        if result:
            print(f"Efficiency Mode enabled for this script. The green leaf should appear in Task Manager.")
        else:
            # Get the last error code
            print(f"Failed to enable Efficiency Mode. Error code: {error_code}")
            
            error_code = GetLastError()
    
            # Common error codes and their meanings
            if error_code == 5:
                print("Error 5: Access Denied. Ensure you're running the script as Administrator.")
            elif error_code == 87:
                print("Error 87: Invalid Parameter. Check the parameters passed to SetProcessInformation.")
            elif error_code == 6:
                print("Error 6: Invalid Handle. Ensure the process handle is valid.")
            else:
                print("Unknown error. Check your Windows version and permissions.")
    
        # Verify the QoS has been set to EcoQoS
        pPState.ControlMask = 0
        pPState.StateMask = 0
    
        verify_result = ctypes.windll.kernel32.GetProcessInformation(
            hProcess,
            ProcessPowerThrottling,
            ctypes.byref(pPState),
            ctypes.sizeof(pPState),
        )
    
        if verify_result:
            print("Power throttling state verified successfully.\n")
        else:
            error_code = GetLastError()
            print(f"Failed to verify power throttling state. Error code: {error_code}")
    
        # Close the process handle
        kernel32.CloseHandle(hProcess)
    
    
    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.