Along comes ChatGPT which solves this issue for me in a couple of minutes.
Basically, I don't want my computer to go to sleep, but I do want my monitor to turn off (standby mode) and lock screen to be activated.
This script is designed to monitor a user's inactivity based on their keyboard and mouse inputs. If the user remains inactive beyond a specified duration (in minutes), the script will automatically lock the workstation and put the monitor to sleep.
Seems to be working well for me, however I'm going to do a bit of testing before I add it as a scheduled task and trigger when the workstation is uunlocked.
** update ** - needs a bit of work.. IE gracefully stopping OBS before running the lock screen a monitor standby commands.. But hopefully serves as a good starting point. Maybe later include an option to check if OBS is actually recording once the timer is reached. But for now, it's a good starting point.
Code:
<#
.SYNOPSIS
LockScreenIdleMonitor.ps1 monitors the user's idle time based on mouse and keyboard activity and locks the screen or puts the monitor into standby when certain idle thresholds are reached.
.DESCRIPTION
LockScreenIdleMonitor.ps1 uses the Windows API to detect the last user activity (from keyboard or mouse).
When the user's cumulative idle time reaches specific thresholds (specified in minutes), the script can
lock the workstation and/or put the monitor to sleep.
.NOTES
File Name : LockScreenIdleMonitor.ps1
Author : ChatGPT from OpenAI
Prerequisite : PowerShell V2
Copyright 2023 : OpenAI
#>
if (-not ([System.Management.Automation.PSTypeName]'IdleActions').Type) {
Add-Type @'
using System;
using System.Runtime.InteropServices;
public static class IdleActions {
[DllImport("user32.dll", SetLastError=false)]
public static extern bool GetLastInputInfo(ref LASTINPUTINFO plii);
[DllImport("user32.dll")]
public static extern void LockWorkStation();
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern int SendMessage(int hWnd, int wMsg, int wParam, int lParam);
[StructLayout(LayoutKind.Sequential)]
public struct LASTINPUTINFO {
public uint cbSize;
public uint dwTime;
}
public static uint GetIdleDuration() {
LASTINPUTINFO lii = new LASTINPUTINFO();
lii.cbSize = (uint)Marshal.SizeOf(typeof(LASTINPUTINFO));
GetLastInputInfo(ref lii);
return ((uint)Environment.TickCount - lii.dwTime);
}
}
'@
}
function Monitor-IdleTime {
param (
[Parameter(Mandatory=$true)]
[int]$LockScreenThresholdMinutes,
[Parameter(Mandatory=$true)]
[int]$MonitorStandbyThresholdMinutes
)
# Constants for monitor sleep and activation
$SC_MONITORPOWER = 0xF170
$WM_SYSCOMMAND = 0x0112
$MONITOR_OFF = 2
$HWND_BROADCAST = 0xFFFF
$lockThresholdSeconds = $LockScreenThresholdMinutes * 60
$monitorThresholdSeconds = $MonitorStandbyThresholdMinutes * 60
while ($true) {
$idleTime = [IdleActions]::GetIdleDuration()
# Convert idleTime from milliseconds to seconds
$idleSeconds = $idleTime / 1000
if ($idleSeconds -ge $lockThresholdSeconds) {
[IdleActions]::LockWorkStation()
# Once locked, we reset the idleSeconds to not immediately turn off the monitor post-lock
$idleSeconds = 0
}
if ($idleSeconds -ge $monitorThresholdSeconds) {
[IdleActions]::SendMessage($HWND_BROADCAST, $WM_SYSCOMMAND, $SC_MONITORPOWER, $MONITOR_OFF)
}
Clear
Write-Output ("Idle for: {0:D2}:{1:D2}" -f [int]($idleSeconds / 60), [int]($idleSeconds % 60))
Start-Sleep -Seconds 5
}
}
Monitor-IdleTime -LockScreenThresholdMinutes 5 -MonitorStandbyThresholdMinutes 10