Add-Type -AssemblyName System.Windows.Forms Add-Type @" using System; using System.Runtime.InteropServices; public static class IdleTime { [StructLayout(LayoutKind.Sequential)] public struct LASTINPUTINFO { public uint cbSize; public uint dwTime; } [DllImport("user32.dll")] public static extern bool GetLastInputInfo(ref LASTINPUTINFO plii); public static uint GetIdleTime() { LASTINPUTINFO lii = new LASTINPUTINFO(); lii.cbSize = (uint)System.Runtime.InteropServices.Marshal.SizeOf(typeof(LASTINPUTINFO)); GetLastInputInfo(ref lii); return ((uint)Environment.TickCount - lii.dwTime) / 1000; // seconds } } "@ function Start-Activity { [CmdletBinding(DefaultParameterSetName="Activity")] param( [Parameter(Mandatory=$true, ParameterSetName="Activity")] [double]$Hours, [Parameter(Mandatory=$true, ParameterSetName="Activity")] [double]$IntervalSeconds, [Parameter(Mandatory=$true, ParameterSetName="TestIdle", HelpMessage="Prints idle time continuously.")] [switch]$TestIdle ) if ($PSCmdlet.ParameterSetName -eq "TestIdle") { Write-Host "Idle monitoring started. Press Ctrl+C to stop." while ($true) { $idleSec = [IdleTime]::GetIdleTime() Write-Host ("Idle time: {0} seconds" -f $idleSec) -NoNewline Write-Host "`r" -NoNewline Start-Sleep -Seconds 1 } } else { Write-Host "Activity started" $endTime = (Get-Date).AddHours($Hours) while ((Get-Date) -lt $endTime) { [System.Windows.Forms.SendKeys]::SendWait("+") Start-Sleep -Milliseconds 100 Start-Sleep -Seconds $IntervalSeconds $remaining = $endTime - (Get-Date) Write-Host ("Time left: {0:hh\:mm\:ss}" -f $remaining) -NoNewline Write-Host "`r" -NoNewline } Write-Host "`nActivity finished" } }