Skip to content

Instantly share code, notes, and snippets.

@gourytch
Created July 30, 2025 07:56
Show Gist options
  • Select an option

  • Save gourytch/4dacfc15b38a15976df9bc45c78483f8 to your computer and use it in GitHub Desktop.

Select an option

Save gourytch/4dacfc15b38a15976df9bc45c78483f8 to your computer and use it in GitHub Desktop.
Set power saving scheme when workstation is locked
<#
# How to enable 4800..4803 events
* run `gpedit.msc`
* goto:
->`Computer Configuration`
->`Windows Settings`
->`Security Settings`
->`Advanced Audit Policy Configuration`
->`System Audit Policies - Local Group Policy Object`
->`Logon/Logoff`
* enable: `Audit Other Logon/Logoff Events`
# How to add CMD-wrapper
* create LockWatcher.cmd
* add: powershell -ExecutionPolicy Bypass -File "%~dp0\LockWatcher.ps1"
#>
# Check and Run with elevated privileges
if (!([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) {
Start-Process powershell.exe "-NoProfile -ExecutionPolicy Bypass -File `"$PSCommandPath`"" -Verb RunAs
exit
}
$logPath = "C:\Temp\LockWatcher.log"
# Ensure log directory exists
$logDirectory = Split-Path $logPath -Parent
if (-not (Test-Path $logDirectory)) {
New-Item -ItemType Directory -Path $logDirectory | Out-Null
}
function Log($message) {
try {
Write-Host $message # Add console output for debugging
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
"$timestamp $message" | Out-File $logPath -Append
}
catch {
Write-Host "... Log error: $_"
}
}
# Power Scheme Functions
function Get-PowerSchemes {
try {
$schemes = @()
$output = powercfg /list 2>&1
foreach ($line in $output) {
if ($line -match 'Power Scheme GUID: ([\d\w-]+)\s+\((.*?)\)\s*(\*)?') {
$schemes += [PSCustomObject]@{
Guid = $matches[1]
Name = $matches[2]
Active = [bool]$matches[3]
}
}
}
return $schemes
}
catch {
Log "Error retrieving power schemes: $_"
return $null
}
}
function Set-PowerScheme($guid) {
try {
$result = powercfg /setactive $guid 2>&1
if ($LASTEXITCODE -ne 0) {
throw $result
}
Log "Switched to power scheme: $((Get-PowerSchemes | Where-Object Guid -eq $guid).Name)"
return $true
}
catch {
Log "Error switching power scheme: $_"
return $false
}
}
# Initialize power schemes with validation
try {
$schemes = Get-PowerSchemes
$powerSaverGuid = ($schemes | Where-Object Name -match 'Power saver').Guid
$balancedGuid = ($schemes | Where-Object Name -match 'Balanced').Guid
if (-not $powerSaverGuid) { throw "Power saver scheme not found" }
if (-not $balancedGuid) { throw "Balanced scheme not found" }
}
catch {
Log "Initialization failed: $_"
exit 1
}
# Event Handler Functions
function global:SetPowerSavingScheme {
Log "set power saving scheme."
Set-PowerScheme $powerSaverGuid | Out-Null
}
function global:SetBalancedScheme {
Log "set balanced scheme."
Set-PowerScheme $balancedGuid | Out-Null
}
# Powered by Active Audit Policy: "Audit Other Logon/Logoff Events" enabled
$ids = @(4800, 4801, 4802, 4803)
Log "--- start ---"
try {
$initial = Get-WinEvent -FilterHashtable @{LogName='Security'; Id=$ids} -MaxEvents 1 -Oldest:$false -ErrorAction Stop
$seen = $initial.RecordId
Log "Set baseline to $seen."
} catch {
# No existing events found
$seen = 0
Log "No existing events found — Set baseline to $seen."
}
Log "Starting polling for Event IDs $($ids -join ', ') from $seen ..."
while ($true) {
try {
$events = Get-WinEvent -FilterHashtable @{LogName='Security'; Id=$ids} -MaxEvents 1 -ErrorAction Stop
}
catch {
if ($_.FullyQualifiedErrorId -like '*NoMatchingEventsFound*') {
# No new relevant events, skip logging
Start-Sleep -Seconds 1
continue
}
else {
# Unexpected error, display and break
Log "Error reading events: $($_.Exception.Message)"
break
}
}
foreach ($evt in $events | Sort-Object RecordId) {
$rec_id = $evt.RecordId
$evt_id = $evt.Id
if ($rec_id -le $seen) { continue }
$seen = $reC_id
$ts = $evt.TimeCreated.ToString("yyyy-MM-dd HH:mm:ss")
Log "I has got the new event: ctime: [$ts], record ID: $rec_id, event ID: $evt_id"
switch ($evt_id) {
4800 {
Log "4800: The workstation was locked."
SetPowerSavingScheme
}
4801 {
Log "4801: The workstation was unlocked."
SetBalancedScheme
}
4802 {
Log "4802: The screen saver was invoked."
SetPowerSavingScheme
}
4803 {
Log "4803: The screen saver was dismissed."
SetBalancedScheme
}
}
}
Start-Sleep -Seconds 1
}
Log "--- finish ---"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment