Hey You,
Let me paint you a picture

You’re working for a customer. A big one. The kind where policies exist… not because people follow them but because Legal needs to sleep at night.
And one of those policies is:
When you leave the office… SHUT DOWN YOUR COMPUTER

Simple right? RIGHT? … no? Of course not. Because there will always be users who:
- “forget”
- “don’t have time”
- “but I was only gone for 17 hours???”
- “I needed to generate 1.21 gigawatts to power this new device which I installed inside the Delorean”
- Or simply think that closing the laptop lid sends it straight to Valhalla
And this client of mine took this policy seriously. Like… SERIOUSLY seriously. Security… Energy… Compliance… Nightly Maintenance… the whole checklist.
So… how do you enforce it?
Easy: You create a GPO that shuts the machine down when idle.
Or… at least… that’s the theory. Because in the real world?
Idle ≠ Safe to Shut down
A computer can be idle while:
- rendering a massive video
- running a Power BI refresh
- processing a script
- uploading files
- sitting with unsaved documents open
- while someone is still connected remotely
- Or when someone tries to plot a scheme to steal plutonium from some Libyan nationalists who hired you to create them a… … never mind
GPO sees none of that. GPO only sees:
No mouse? No keyboard? -> Must be sleeping -> KILL IT WITH FIRE

Perfect if your organization is filled exclusively with interns and psychopaths. But not perfect for a customer who has legitimate long-running workloads.
So… what do you do?
You build something yourself. In PowerShell. Obviously
I needed something smarter, something polite, something that didn’t kill a 3D render because someone went to lunch.
So… I wrote a script. A beautiful, slightly chaotic, very Engin-Style script.
# Time in seconds for idle detection (10 hours)
$idleTime = 36000
# Countdown time in seconds (2 hours)
$countdownTime = 7200
# Define the script for the pop-up
Add-Type -AssemblyName PresentationFramework
Add-Type @"
using System;
using System.Runtime.InteropServices;
public static class IdleTime
{
[StructLayout(LayoutKind.Sequential)]
struct LASTINPUTINFO
{
public uint cbSize;
public uint dwTime;
}
[DllImport("user32.dll")]
static extern bool GetLastInputInfo(ref LASTINPUTINFO plii);
public static uint GetIdleTime()
{
LASTINPUTINFO lastInputInfo = new LASTINPUTINFO();
lastInputInfo.cbSize = (uint)Marshal.SizeOf(typeof(LASTINPUTINFO));
GetLastInputInfo(ref lastInputInfo);
return ((uint)Environment.TickCount - lastInputInfo.dwTime) / 1000;
}
}
"@
function Show-Popup {
[void][System.Reflection.Assembly]::LoadWithPartialName('System.Windows.Forms')
[void][System.Reflection.Assembly]::LoadWithPartialName('System.Drawing')
# Create form
$form = New-Object Windows.Forms.Form
$form.Text = "Idle Warning"
$form.Size = New-Object Drawing.Size(500, 200)
$form.StartPosition = "CenterScreen"
$form.TopMost = $true
# Label for the message
$label = New-Object Windows.Forms.Label
$label.Text = "The computer has been idle for 10 hours. The computer will shutdown after 2 hours."
$label.AutoSize = $true
$label.Location = New-Object Drawing.Point(10, 20)
$form.Controls.Add($label)
# Countdown label
$countdownLabel = New-Object Windows.Forms.Label
$countdownLabel.Text = "Time remaining: 02:00:00"
$countdownLabel.AutoSize = $true
$countdownLabel.Location = New-Object Drawing.Point(10, 60)
$form.Controls.Add($countdownLabel)
# Shutdown Now button
$shutdownButton = New-Object Windows.Forms.Button
$shutdownButton.Text = "Shutdown Now"
$shutdownButton.Size = New-Object Drawing.Size(100, 40)
$shutdownButton.Location = New-Object Drawing.Point(50, 100)
$shutdownButton.Add_Click({
Stop-Timer
Shutdown-Computer
$form.Close()
})
$form.Controls.Add($shutdownButton)
# Cancel Shutdown button
$cancelButton = New-Object Windows.Forms.Button
$cancelButton.Text = "Cancel Shutdown"
$cancelButton.Size = New-Object Drawing.Size(100, 40)
$cancelButton.Location = New-Object Drawing.Point(200, 100)
$cancelButton.Add_Click({
Stop-Timer
[System.Windows.Forms.MessageBox]::Show("Shutdown canceled.")
$form.Close()
})
$form.Controls.Add($cancelButton)
# Function to stop the timer
function Stop-Timer {
if ($global:timer) {
$global:timer.Stop()
$global:timer.Dispose()
}
}
# Function to shutdown the computer
function Shutdown-Computer {
Stop-Timer
Stop-Computer -Force
}
# Set up timer for countdown using System.Windows.Forms.Timer
$global:timer = New-Object Windows.Forms.Timer
$global:timer.Interval = 1000 # 1 second
$global:timer.Add_Tick({
$global:countdownTime -= 1
$timeSpan = [System.TimeSpan]::FromSeconds($global:countdownTime)
$countdownLabel.Text = "Time remaining: " + $timeSpan.ToString("hh\:mm\:ss")
if ($global:countdownTime -le 0) {
Shutdown-Computer
$form.Close()
}
})
$global:timer.Start()
# Show the form
$form.Add_Shown({$form.Activate()})
[void]$form.ShowDialog()
}
# Idle detection loop
while ($true) {
# Get the system idle time in seconds
$idleSeconds = [IdleTime]::GetIdleTime()
if ($idleSeconds -ge $idleTime) {
Show-Popup
}
# Check every 60 seconds
Start-Sleep -Seconds 60
}And this is what it does:
- Detects real idle time using the Windows API
- Pops up a Windows Form
- Show a 2-hour countdown
- Lets the user choose:
- Shut Down Now
- Cancel Shutdown
- And only shuts the machine down if the user actually abandoned the device.
It’s basically a polite “Bruh… are you still there?” assistant. And let’s be honest, after 12 hours? If you still haven’t checked your machine, it deserves to be shutdown.
Let’s break it down
1. Detecting real idle time (not the fake GPO one)
I call the Windows API “GetLastInputInfo” through a little C# class inside Powershell. Yes… I know… C# inside powershell.
Don’t judge me.
2. 10 hours of real idle -> Trigger the popup
Because yes… people actually leave devices unattended for 10 hours.
3. The popup appears
The popup basically says:
Yo… your machine… you know… has been idle for 10 hours.
I’m giving you 2 hours to fix your life choices. We can get the plutonium somewhere else… like… lightning or something
And then… the timer starts ticking.

4. User chooses
The red pill… or the blue pill? Wait… that’s the Matrix… we were talking about Back to the Future a minute ago. I’m confused…

- Shutdown Now -> Immediate shutdown
- Cancel Shutdown -> “Okay buddy… you win this round”
5. If nobody answers -> Shutdown
If you ignore my popup for 2 hours… I assume you’re either:
- Home
- Fired
- Kidnapped
- Playing the guitar to get your parents kiss each other so that your hand will come back and start playing Johnny be good which then Chuck Berry will steal your song just by listening to it for 2 seconds… like what was that btw???
Either way: PC goes off
Why this works (and why GPO doesn’t)
The solution is:
- Context-aware
- Only triggers after extreme idle time which GPO doesn’t have
- User-Friendly
- You get TWO HOURS to stop it
- Faile-Safe
- No user interaction for 12 hours? Shutdown
- Easy to deploy
- SCCM
- Intune
- GPO Logon script
- Scheduled task
Your pick
Conclusion
Now, I know some PowerShell gurus out there are judging my script.

Users will forever find a way to break policies. So instead of fighting them… I built something that gives them a choice
- Either take responsibility
- Or I’ll take the responsibility for you
A simple PowerShell script that solves a real problem in the real world.
Thanks for reading.
Cheers,
Engin
Pingback: Microsoft Roadmap, messagecenter and blogs updates from 20-11-2025 - KbWorks - SharePoint and Teams Specialist