Profile Image

Michael Simmons

SOC Analyst

PowerShell Anti-Idle Script

I developed a PowerShell script to prevent the system from idling, locking or turning off the monitors. It will also ensure team’s idle will not trigger. Save as anti-idle.ps1 and call it via a batch file for simplicity. 

Batch – anti-idle.bat

@echo off

start "" "%SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe" -noexit -command "& ""C:\scripts\anti-idlet.ps1"""

PowerShell – anti-idle.ps1

Add-Type -TypeDefinition @"
 using System;
 using System.Diagnostics;
 using System.Runtime.InteropServices;

namespace ThreadModule
{
    public struct LASTINPUTINFO
    {
        public uint cbSize;
        public uint dwTime;
    }
    public enum ExecutionState : uint
    {
        ES_AWAYMODE_REQUIRED = 0x00000040,
        ES_CONTINUOUS = 0x80000000,
        ES_DISPLAY_REQUIRED = 0x00000002,
        ES_SYSTEM_REQUIRED = 0x00000001
        // Legacy flag, should not be used.
        // ES_USER_PRESENT = 0x00000004
    }

    public static class ThreadManagement
    {
        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern ExecutionState SetThreadExecutionState(ExecutionState esFlags);

        [DllImport("User32.dll")]
        private static extern bool GetLastInputInfo(ref LASTINPUTINFO plii);

        [DllImport("Kernel32.dll")]
        private static extern uint GetLastError();

        public static uint GetIdleTime()
        {
            LASTINPUTINFO lastInPut = new LASTINPUTINFO();
            lastInPut.cbSize = (uint)System.Runtime.InteropServices.Marshal.SizeOf(lastInPut);
            GetLastInputInfo(ref lastInPut);

            return ((uint)Environment.TickCount - lastInPut.dwTime);
        }
    /// <summary>
    /// Get the Last input time in milliseconds
    /// </summary>
    /// <returns></returns>
        public static long GetLastInputTime()
        {
            LASTINPUTINFO lastInPut = new LASTINPUTINFO();
            lastInPut.cbSize = (uint)System.Runtime.InteropServices.Marshal.SizeOf(lastInPut);
            if (!GetLastInputInfo(ref lastInPut))
            {
                throw new Exception(GetLastError().ToString());
            }
            return lastInPut.dwTime;
        }
    }
}
"@


Add-Type -AssemblyName System.Windows.Forms
for ($i = 0; $i -lt 9; $i++)
{
    Write-Host ""
}
Write-Host "Enabling anti idle measures! Thread state now set to: " -NoNewline
[ThreadModule.ThreadManagement]::SetThreadExecutionState([ThreadModule.ExecutionState]::ES_CONTINUOUS + [ThreadModule.ExecutionState]::ES_DISPLAY_REQUIRED)
Write-Host "Press any key to exit: "
$Pos = [System.Windows.Forms.Cursor]::Position
$PosDelta = 1
$closeScript = $true
$maxTimeInSeconds = 300
$wshell = New-Object -ComObject wscript.shell
do
{
    if ([Console]::KeyAvailable)
    {
        $key = [Console]::ReadKey();
        if ($key.key -eq 'F15')
        {
        }
        else
        {
            $closeScript = $false
        }
    }
    else
    {
        $lastInputTime = [ThreadModule.ThreadManagement]::GetIdleTime()
        $time = New-TimeSpan -Seconds ( $lastInputTime / 1000 )
        if ($time.TotalSeconds -gt $maxTimeInSeconds)
        {
            Write-Host "$(Get-Date) Generating activity, Press any key to exit:"
            $outlookTitle = Get-Process -Name *outlook* | select mainwindowtitle
            $teamsTitle = Get-Process -Name *teams* | where { $_.MainWindowTitle -ne '' } | select mainwindowtitle
            Write-Host "Outlook: $($outlookTitle.MainWindowTitle)"
            $appResult = $wshell.AppActivate("$($outlookTitle.MainWindowTitle)")
            Write-Host "Teams: $($teamsTitle.MainWindowTitle)"
            $appResult = $wshell.AppActivate("$($teamsTitle.MainWindowTitle)")
            $wshell.SendKeys("{F15}")
            [System.Windows.Forms.Cursor]::Position = New-Object System.Drawing.Point((($Pos.X) + $PosDelta) , $Pos.Y)
            [System.Windows.Forms.Cursor]::Position = New-Object System.Drawing.Point((($Pos.X) - $PosDelta) , $Pos.Y)
        }
        else
        {
            Write-Progress -Activity "Waiting to generate activity, press any key to exit. Time since last input $($time.Duration())" -Status $true -PercentComplete ($time.TotalSeconds/$maxTimeInSeconds*100) -SecondsRemaining ($maxTimeInSeconds-$time.TotalSeconds)
        }
        Start-Sleep -Seconds 1
    }


} while ($closeScript)

Write-Host "Disabling anti idle measures, and exiting!"

[ThreadModule.ThreadManagement]::SetThreadExecutionState([ThreadModule.ExecutionState]::ES_CONTINUOUS)

Leave a Reply

Your email address will not be published. Required fields are marked *