Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # ==============================================================================
- # PABS: Powerplan And Brightness Selector (v1.1)
- # A lightweight utility to automate Windows Power Plans and Brightness levels.
- # written by MaxK https://www.reddit.com/user/Glad-Journalist-4807/
- # on ThinkPad X390/T14s gen 1 hybrid
- # Please keep the credits intact :)
- #
- # Changes:
- # 1. PS 7 compatibility corrections: replaced ContextMenu with ContextMenuStrip, MenuItems -> Items and MenuItem ->ToolStripMenuItem.
- # ==============================================================================
- # CONFIGURATION
- # list of defined power plans mapped to their system GUIDs
- $PowerPlans = @{
- "Ultra" = "e9a42b02-d5df-448d-aa00-03f14749eb61"
- "High" = "8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c"
- "Balanced" = "381b4222-f694-41f0-9685-ff5bb260df2e"
- "PwrSaver" = "a1841308-3541-4fab-bc81-f71556f20b4a"
- }
- # Default plan when on AC and no specific rules from the watchlist match
- $DefaultPPAC = "Balanced"
- # Default plan when on Battery and no specific rules from the watchlist match
- $DefaultPPBattery = "PwrSaver"
- # When set to 1, the current brightness level is preserved and set after switching plans
- $AutoInheritBrightness = 1
- # AC Watchlist - Priority is TOP-DOWN (first matching directory wins)
- $WatchListAC = @(
- @{ Path = "C:\Games\*"; Plan = "Ultra" }
- @{ Path = "c:\Tools\OpenShot Video Editor\*"; Plan = "Ultra" }
- @{ Path = "C:\Program Files\Mozilla Firefox\*"; Plan = "High" }
- @{ Path = "c:\Program Files\DAUM\PotPlayer\*"; Plan = "PwrSaver" }
- )
- # Battery Watchlist - Again the priority is TOP-DOWN (first matching directory wins)
- $WatchListBattery = @(
- @{ Path = "C:\Games\*"; Plan = "Balanced" }
- @{ Path = "C:\Program Files\*"; Plan = "PwrSaver" }
- )
- # Interval for checking running processes and switching plans (in seconds)
- $ProcessCheckInterval = 5
- # Interval for polling keyboard state (Ctrl+Shift+B) in milliseconds
- $KeyCheckInterval = 50
- # Standard Windows GUID for the Video/Display subgroup
- $DisplaySubGroup = "7516b95f-f776-4464-8c53-06167f40cc99"
- # end of CONFIGURATION
- #WIN32 API&UTILS
- $WinFuncs = @"
- [DllImport("user32.dll")] public static extern IntPtr GetSystemMenu(IntPtr hWnd, bool bRevert);
- [DllImport("user32.dll")] public static extern bool EnableMenuItem(IntPtr hMenu, uint uIDEnableItem, uint uEnable);
- [DllImport("user32.dll")] public static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);
- [DllImport("user32.dll")] public static extern bool IsWindowVisible(IntPtr hWnd);
- [DllImport("user32.dll")] public static extern short GetAsyncKeyState(int vKey);
- [DllImport("powrprof.dll")] public static extern uint PowerGetActiveScheme(IntPtr UserRootPowerKey, out IntPtr ActivePolicyGuiPtr);
- "@
- $Win32 = Add-Type -MemberDefinition $WinFuncs -Name "Win32Utils" -Namespace Win32 -PassThru
- # get console window
- $ConsolePtr = (Get-Process -Id $PID).MainWindowHandle
- # disable the "X" (Close) button to prevent accidental exit
- function Disable-CloseButton {
- $hMenu = [Win32.Win32Utils]::GetSystemMenu($ConsolePtr, $false)
- [void][Win32.Win32Utils]::EnableMenuItem($hMenu, 0xF060, 0x00000001)
- Write-Host "Disabling X"
- }
- # start the script hidden and lock the close button
- [void][Win32.Win32Utils]::ShowWindowAsync($ConsolePtr, 0) # 0 = SW_HIDE
- Disable-CloseButton
- # find the GUID of the "Display brightness"
- $BrightGUID = $null
- $query = powercfg /q SCHEME_CURRENT SUB_VIDEO
- foreach ($line in $query) {
- if ($line -match "GUID:\s+([\w-]+).+\(Display brightness\)") {
- $BrightGUID = $matches[1].Trim(); break
- }
- }
- # tray icon
- Add-Type -AssemblyName System.Windows.Forms, System.Drawing
- $TrayIcon = New-Object System.Windows.Forms.NotifyIcon
- $TrayIcon.Icon = [System.Drawing.Icon]::ExtractAssociatedIcon((Get-Process -Id $PID).Path)
- $TrayIcon.Visible = $true
- $ContextMenu = New-Object System.Windows.Forms.ContextMenuStrip
- $StatusItem = New-Object System.Windows.Forms.ToolStripMenuItem -Property @{ Enabled = $false; Text = "Plan: Init..." }
- # dashboard
- $ToggleItem = New-Object System.Windows.Forms.ToolStripMenuItem
- $ToggleItem.Text = "Show Dashboard"
- $ToggleItem.add_Click({
- if ([Win32.Win32Utils]::IsWindowVisible($ConsolePtr)) {
- [void][Win32.Win32Utils]::ShowWindowAsync($ConsolePtr, 0) # Hide
- $ToggleItem.Text = "Show Dashboard"
- } else {
- [void][Win32.Win32Utils]::ShowWindowAsync($ConsolePtr, 5) # Show
- Disable-CloseButton
- $ToggleItem.Text = "Minimize to tray"
- }
- })
- $ExitItem = New-Object System.Windows.Forms.ToolStripMenuItem -Property @{ Text = "Exit" }
- $ExitItem.add_Click({ $TrayIcon.Visible = $false; [void](Stop-Process -Id $PID) })
- [void]$ContextMenu.Items.Add($StatusItem)
- [void]$ContextMenu.Items.Add("-")
- [void]$ContextMenu.Items.Add($ToggleItem)
- [void]$ContextMenu.Items.Add($ExitItem)
- $TrayIcon.ContextMenuStrip = $ContextMenu
- function Write-Log ($msg, $color = "White") {
- $timestamp = Get-Date -Format "HH:mm:ss"
- Write-Host "[$timestamp] $msg" -ForegroundColor $color
- }
- # get currebnt brightness
- function Get-CurrentBrightness {
- $bObj = Get-CimInstance -Namespace root/WMI -ClassName WmiMonitorBrightness | Select-Object -First 1
- return $bObj.CurrentBrightness
- }
- # set brightness level for both AC and DC modes for a target plan
- function Set-PlanBrightness ($targetGuid, $brightness) {
- if ($null -eq $BrightGUID) { return }
- [void](Start-Process "powercfg.exe" -ArgumentList "/setacvalueindex $targetGuid $DisplaySubGroup $BrightGUID $brightness" -WindowStyle Hidden -Wait)
- [void](Start-Process "powercfg.exe" -ArgumentList "/setdcvalueindex $targetGuid $DisplaySubGroup $BrightGUID $brightness" -WindowStyle Hidden -Wait)
- }
- function Get-IsOnAC {
- $battery = Get-CimInstance -ClassName Win32_Battery -ErrorAction SilentlyContinue
- if ($null -eq $battery) { return $true }
- return $battery.BatteryStatus -eq 2
- }
- function Get-ActivePlanGuid {
- $ptr = [IntPtr]::Zero
- [void][Win32.Win32Utils]::PowerGetActiveScheme([IntPtr]::Zero, [ref]$ptr)
- if ($ptr -ne [IntPtr]::Zero) {
- return ([System.Runtime.InteropServices.Marshal]::PtrToStructure($ptr, [type][Guid])).ToString().ToLower()
- }
- return ""
- }
- # main loop
- $lastProcessCheck = [DateTime]::MinValue
- Write-Log "PABS v1.0 Started" "Cyan"
- while ($true) {
- [System.Windows.Forms.Application]::DoEvents()
- # Ctrl+Shift+B monitoring
- # set the current brightness level to all power plans defined in $PowerPlans
- if (($Win32::GetAsyncKeyState(17) -band 0x8000) -and ($Win32::GetAsyncKeyState(16) -band 0x8000) -and ($Win32::GetAsyncKeyState(66) -band 0x8000)) {
- $currB = Get-CurrentBrightness
- Write-Log "Syncing brightness: $currB% to ALL plans" "Magenta"
- foreach ($guid in $PowerPlans.Values) { Set-PlanBrightness $guid $currB }
- [void](powercfg /setactive (Get-ActivePlanGuid))
- Start-Sleep -Milliseconds 500
- }
- # monitoring and AC/battery logic
- if ([DateTime]::Now -gt $lastProcessCheck.AddSeconds($ProcessCheckInterval)) {
- $IsOnAC = Get-IsOnAC
- $CurrentWL = if($IsOnAC){$WatchListAC}else{$WatchListBattery}
- $TargetAlias = if($IsOnAC){$DefaultPPAC}else{$DefaultPPBattery}
- # get list of running processes with a file path
- $procs = Get-Process | Where-Object { $_.Path } | Select-Object -Property Path
- $TriggeringPath = "Default (No match)"
- # priority matching loop
- :OuterLoop foreach ($item in $CurrentWL) {
- foreach ($p in $procs) {
- if ($p.Path -like $item.Path) {
- $TargetAlias = $item.Plan
- $TriggeringPath = $p.Path # Store the path that caused the match
- break OuterLoop
- }
- }
- }
- # if no match then default
- if ($TriggeringPath -eq "Default (No match)") {
- $TriggeringPath = "No watched process running"
- }
- if ($PowerPlans.ContainsKey($TargetAlias)) {
- $TargetGUID = $PowerPlans[$TargetAlias].ToLower()
- $ActiveGUID = Get-ActivePlanGuid
- $mode = if($IsOnAC){"AC"}else{"BAT"}
- $StatusItem.Text = "Plan: $TargetAlias [$mode]"
- $TrayIcon.Text = "PABS: $TargetAlias ($mode)"
- if ($ActiveGUID -ne $TargetGUID) {
- # inherit current brightness to the target plan if enabled
- if ($AutoInheritBrightness -eq 1) {
- $currB = Get-CurrentBrightness
- Write-Log "Inheriting brightness: $currB% for $TargetAlias" "Gray"
- Set-PlanBrightness $TargetGUID $currB
- }
- # apply the target power plan
- [void](Start-Process "powercfg.exe" -ArgumentList "/setactive $TargetGUID" -WindowStyle Hidden -Wait)
- Write-Log "Switching to $TargetAlias ($mode). Triggered by: $TriggeringPath" "Yellow"
- }
- }
- $lastProcessCheck = [DateTime]::Now
- # ensure Close button remains disabled if the dashboard is visible
- if ([Win32.Win32Utils]::IsWindowVisible($ConsolePtr)) { Disable-CloseButton }
- }
- Start-Sleep -Milliseconds $KeyCheckInterval
- }
Advertisement
Add Comment
Please, Sign In to add comment