Skip to content

Instantly share code, notes, and snippets.

@windoze95
Last active August 5, 2025 15:13
Show Gist options
  • Select an option

  • Save windoze95/e52712434a98967e46dfcb46b0044b09 to your computer and use it in GitHub Desktop.

Select an option

Save windoze95/e52712434a98967e46dfcb46b0044b09 to your computer and use it in GitHub Desktop.
A no sleep script for Windows that moves the cursor in the shape of a heart every two minutes.
<# --------------------------------------------------------------------
No Sleep v2.2 - 2025
- Moves the cursor in the shape of a heart every 120s.
- Pauses after a set time of true user absence to allow the computer to sleep.
- Default pause time is 2 hours, but can be overridden with an argument (e.g., .\script.ps1 1.5).
- Designed to work in locked-down corporate environments, avoids the use of external DLLs or WMI.
-------------------------------------------------------------------- #>
#region -- WIN32 API HELPERS (Idle Time & Mouse Nudge) --
# Define the C# types only if any of them are missing from the current session.
if (-not ('NativeIdle' -as [type]) -or -not ('MouseInject' -as [type])) {
try {
Add-Type -TypeDefinition @'
using System;
using System.Runtime.InteropServices;
// Checks how long the user has been idle
public static class NativeIdle {
[StructLayout(LayoutKind.Sequential)]
private struct LASTINPUTINFO { public uint cbSize, dwTime; }
[DllImport("user32.dll")]
private static extern bool GetLastInputInfo(ref LASTINPUTINFO lii);
public static uint Millis() {
var lii = new LASTINPUTINFO { cbSize = (uint)Marshal.SizeOf(typeof(LASTINPUTINFO)) };
GetLastInputInfo(ref lii);
return unchecked((uint)Environment.TickCount - lii.dwTime);
}
}
// Moves the mouse slightly to reset the idle timer
public static class MouseInject {
[DllImport("user32.dll")]
public static extern void mouse_event(uint flags, uint dx, uint dy, uint data, UIntPtr extra);
public const uint MOVE = 0x0001;
public static void Nudge() {
mouse_event(MOVE, 0, 0, 0, UIntPtr.Zero);
}
}
'@
} catch {
Write-Error "Failed to compile NativeIdle/MouseInject types: $_"
exit 1
}
}
#endregion
#region -- HEART PATH PRECOMPUTE --
Add-Type -AssemblyName System.Windows.Forms | Out-Null
$heart = 0..59 | ForEach-Object {
$t = 2 * [Math]::PI * $_ / 60
$x = 16 * [Math]::Pow([Math]::Sin($t), 3)
$y = 13 * [Math]::Cos($t) - 5 * [Math]::Cos(2*$t) - 2 * [Math]::Cos(3*$t) - [Math]::Cos(4*$t)
[System.Drawing.Point]::new([int]($x * 4), [int](-$y * 4))
}
#endregion
#region -- PARAMETERS & STATE --
$jiggleThresholdMs = 118000 # 118s: Idle time before drawing heart.
$stepDelay = [int](2000 / $heart.Count) # ~33ms per point -> 2s full trace.
$triggered = $false # One-heart-per-idle guard.
$lastPhysicalActivity = Get-Date # The master timestamp for the "true-idle" check.
$ignoreNextUpdate = $false # Flag to ignore script-induced idle reset after nudge.
# --- Pause Threshold Logic with User Override ---
$pauseThresholdHours = 2.0 # Default to 2 hours
if ($args.Count -gt 0) {
$userInput = $args[0]
if ($userInput -as [double]) {
$providedHours = $userInput -as [double]
if ($providedHours -gt 0) {
$pauseThresholdHours = $providedHours
Write-Host ("Override detected. Setting pause time to {0} hours." -f $pauseThresholdHours) -ForegroundColor Yellow
} else { Write-Warning "Pause time must be a positive number. Using default." }
} else { Write-Warning "Invalid input '$userInput'. Not a number. Using default." }
}
$pauseThresholdSecs = [int]($pauseThresholdHours * 3600)
# --- SANITY CHECK: The pause threshold must be longer than the jiggle threshold. ---
$jiggleThresholdSecs = $jiggleThresholdMs / 1000
if ($pauseThresholdSecs -le $jiggleThresholdSecs) {
Write-Warning "The pause time ($pauseThresholdSecs s) cannot be less than the jiggle time ($jiggleThresholdSecs s)."
$pauseThresholdSecs = $jiggleThresholdSecs + 2 # Add 2 seconds to ensure at least one jiggle can happen.
$pauseThresholdHours = [Math]::Round($pauseThresholdSecs / 3600, 4)
Write-Warning "Automatically adjusting pause time to $pauseThresholdSecs seconds (~$pauseThresholdHours hours)."
}
#endregion
#region -- MAIN LOOP --
Write-Host "Script started. Jiggle threshold: $jiggleThresholdSecs seconds. Pause threshold: $pauseThresholdHours hours ($pauseThresholdSecs seconds)."
while ($true) {
$systemIdleMs = [NativeIdle]::Millis()
# If system idle time is low, it means the user is physically active.
if ($systemIdleMs -lt 1000) {
if (-not $ignoreNextUpdate) {
$lastPhysicalActivity = Get-Date
}
$ignoreNextUpdate = $false # Reset flag after check (whether updated or not).
}
# Calculate how long it's been since the last physical activity.
$trueIdleSecs = ((Get-Date) - $lastPhysicalActivity).TotalSeconds
# PAUSE if true-idle time has exceeded the pause threshold.
if ($trueIdleSecs -ge $pauseThresholdSecs) {
Write-Host ("{0:T} - True-idle of {1:N0}s exceeded pause threshold. Pausing..." -f (Get-Date), $trueIdleSecs) -ForegroundColor Gray
Start-Sleep -Seconds 15
continue
}
# JIGGLE if system idle time has exceeded the jiggle threshold.
if (-not $triggered -and $systemIdleMs -ge $jiggleThresholdMs) {
$origin = [System.Windows.Forms.Cursor]::Position
$aborted = $false
Write-Host ("{0:T} - Jiggle threshold reached ({1:N0}ms). Drawing heart..." -f (Get-Date), $systemIdleMs) -ForegroundColor Green
foreach ($pt in $heart) {
[System.Windows.Forms.Cursor]::Position = [System.Drawing.Point]::new($origin.X + $pt.X, $origin.Y + $pt.Y)
Start-Sleep -Milliseconds $stepDelay
if ([NativeIdle]::Millis() -lt 1000) {
Write-Host ("{0:T} - User activity detected. Aborting draw." -f (Get-Date)) -ForegroundColor Yellow
$aborted = $true
break
}
}
if (-not $aborted) {
[System.Windows.Forms.Cursor]::Position = $origin
[MouseInject]::Nudge()
$ignoreNextUpdate = $true # Set flag to ignore the next low-idle update caused by this nudge.
$triggered = $true
}
}
# Reset heart trigger once user returns to an active state.
if ($triggered -and $systemIdleMs -lt $jiggleThresholdMs) { $triggered = $false }
# Sleep intelligently until the next check.
$msToGo = $jiggleThresholdMs - $systemIdleMs - 500
$sleep = if ($msToGo -gt 500) { $msToGo } else { 500 }
Start-Sleep -Milliseconds $sleep
}
#endregion
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment