Last active
August 5, 2025 15:13
-
-
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <# -------------------------------------------------------------------- | |
| 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