Is there a way to get the idle time of the machine, as in the amount of time the machine has not been used for, in minutes/hours using Powershell or a batch file?
Idle time is paid time that an employee, or machine, is unproductive due to factors that can either be controlled or uncontrolled by management.
Examples of normal idle time include employee breaks, routine maintenance, and machine set-up time.
The accounting treatment of idle time is that it is treated as indirect labor cost and should, therefore, be included in manufacturing overhead cost. Idle Time = Total Time spent by a worker – Actual Time spent on production.
Here's a PowerShell solution that uses the Win32 API GetLastInputInfo.
Add-Type @'
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace PInvoke.Win32 {
public static class UserInput {
[DllImport("user32.dll", SetLastError=false)]
private static extern bool GetLastInputInfo(ref LASTINPUTINFO plii);
[StructLayout(LayoutKind.Sequential)]
private struct LASTINPUTINFO {
public uint cbSize;
public int dwTime;
}
public static DateTime LastInput {
get {
DateTime bootTime = DateTime.UtcNow.AddMilliseconds(-Environment.TickCount);
DateTime lastInput = bootTime.AddMilliseconds(LastInputTicks);
return lastInput;
}
}
public static TimeSpan IdleTime {
get {
return DateTime.UtcNow.Subtract(LastInput);
}
}
public static int LastInputTicks {
get {
LASTINPUTINFO lii = new LASTINPUTINFO();
lii.cbSize = (uint)Marshal.SizeOf(typeof(LASTINPUTINFO));
GetLastInputInfo(ref lii);
return lii.dwTime;
}
}
}
}
'@
And an example usage:
for ( $i = 0; $i -lt 10; $i++ ) {
Write-Host ("Last input " + [PInvoke.Win32.UserInput]::LastInput)
Write-Host ("Idle for " + [PInvoke.Win32.UserInput]::IdleTime)
Start-Sleep -Seconds (Get-Random -Minimum 1 -Maximum 5)
}
This vbscript code is inspired from the answered question to show you how we can use it for Auto-Shutdown your workstation after Idle Timeout !
Auto-Shutdown_On_Idle_TimeOut.vbs
'##########################################################################################################################
'# Auto-Shutdown your workstation after Idle Timeout #
'# Script Name : Auto-Shutdown_On_Idle_TimeOut.vbs #
'# Arrêt automatique de votre poste de travail après le délai d'inactivité #
'# Idea comes from here ==> This snippet is from http://stackoverflow.com/a/15846912 #
'# https://stackoverflow.com/questions/15845508/get-idle-time-of-machine/15846912#15846912 #
'# https://gist.github.com/wendelb/1c364bb1a36ca5916ca4 ===> Auto-Lock your workstation after Idle-Timeout with PowerShell#
'##########################################################################################################################
Option Explicit
Dim Copyright,Msg,MsgEN,MsgFR
Copyright = "Auto-Shutdown your workstation after Idle Timeout " & ChrW(169) &" Hackoo 2020"
MsgEN = Array("ATTENTION ! There is another instance running !",_
"Save your Work because the computer will shutdown in 60 seconds")
MsgFR = Array("ATTENTION ! Il y a une autre instance en cours d'exécution !",_
"Sauvegarder votre Travail car l'ordinateur va s'éteindre dans 60 secondes")
If AppPrevInstance() Then
If Oslang = 1036 Then
Msg = MsgFR(0)
Else
Msg = MsgEN(0)
End If
MsgBox Msg & VbCrLF & CommandLineLike(WScript.ScriptName),VbExclamation,Copyright
WScript.Quit
Else
Dim Timeout_Idle,strCommand,VbsPath,ShortcutName
If Oslang = 1036 Then
Msg = MsgFR(1)
Else
Msg = MsgEN(1)
End If
Timeout_Idle = "60" '60 Minutes = 1 Heure = 1 Hour
strCommand = "Shutdown.exe -s -t 60 -c " & DblQuote(Msg)
VbsPath = Wscript.ScriptFullName
ShortcutName = "Auto-Shutdown_On_Idle_TimeOut"
Call Shortcut(VbsPath,ShortcutName)
Call Write_Run_PScript(Timeout_Idle,strCommand)
End If
'---------------------------------------------------------------------------------------------------------------
Sub Shortcut(PathApplication,ShortcutName)
Dim objShell,StartFolder,objShortCut,MyTab
Set objShell = CreateObject("WScript.Shell")
MyTab = Split(PathApplication,"\")
If ShortcutName = "" Then
ShortcutName = MyTab(UBound(MyTab))
End if
StartFolder = objShell.SpecialFolders("Startup")
Set objShortCut = objShell.CreateShortcut(StartFolder & "\" & ShortcutName & ".lnk")
objShortCut.TargetPath = DblQuote(PathApplication)
ObjShortCut.IconLocation = "%SystemRoot%\system32\SHELL32.dll,27"
objShortCut.Save
End Sub
'---------------------------------------------------------------------------------------------------------------
Function DblQuote(Str)
DblQuote = Chr(34) & Str & Chr(34)
End Function
'---------------------------------------------------------------------------------------------------------------
Sub Write_Run_PScript(Timeout_Idle,strCommand)
Const ForWriting = 2
Dim fs,Ws,ts,Ret,PSFile,ByPassPSFile
Set fs = CreateObject("Scripting.FileSystemObject")
Set Ws = CreateObject("WScript.Shell")
PSFile = Ws.ExpandEnvironmentStrings("%Temp%") & fs.GetTempName & ".ps1"
ByPassPSFile = "PowerShell -ExecutionPolicy bypass -noprofile -file "
Set ts = fs.OpenTextFile(PSFile,ForWriting,True)
ts.WriteLine "$idle_timeout = New-TimeSpan -Minutes "& Timeout_Idle &""
ts.WriteLine "Add-Type @'"
ts.WriteLine "using System;"
ts.WriteLine "using System.Diagnostics;"
ts.WriteLine "using System.Runtime.InteropServices;"
ts.WriteLine "namespace PInvoke.Win32 {"
ts.WriteLine " public static class UserInput {"
ts.WriteLine " [DllImport(""user32.dll"", SetLastError=false)]"
ts.WriteLine " private static extern bool GetLastInputInfo(ref LASTINPUTINFO plii);"
ts.WriteLine " [StructLayout(LayoutKind.Sequential)]"
ts.WriteLine " private struct LASTINPUTINFO {"
ts.WriteLine " public uint cbSize;"
ts.WriteLine " public int dwTime;"
ts.WriteLine " }"
ts.WriteLine " public static DateTime LastInput {"
ts.WriteLine " get {"
ts.WriteLine " DateTime bootTime = DateTime.UtcNow.AddMilliseconds(-Environment.TickCount);"
ts.WriteLine " DateTime lastInput = bootTime.AddMilliseconds(LastInputTicks);"
ts.WriteLine " return lastInput;"
ts.WriteLine " }"
ts.WriteLine " }"
ts.WriteLine " public static TimeSpan IdleTime {"
ts.WriteLine " get {"
ts.WriteLine " return DateTime.UtcNow.Subtract(LastInput);"
ts.WriteLine " }"
ts.WriteLine " }"
ts.WriteLine " public static int LastInputTicks {"
ts.WriteLine " get {"
ts.WriteLine " LASTINPUTINFO lii = new LASTINPUTINFO();"
ts.WriteLine " lii.cbSize = (uint)Marshal.SizeOf(typeof(LASTINPUTINFO));"
ts.WriteLine " GetLastInputInfo(ref lii);"
ts.WriteLine " return lii.dwTime;"
ts.WriteLine " }"
ts.WriteLine " }"
ts.WriteLine " }"
ts.WriteLine "}"
ts.WriteLine "'@"
ts.WriteLine "$locked = 0;"
ts.WriteLine "Do {"
ts.WriteLine " $idle_time = [PInvoke.Win32.UserInput]::IdleTime;"
ts.WriteLine " if (($locked -eq 0) -And ($idle_time -gt $idle_timeout)) {"
ts.WriteLine " "&strCommand&""
ts.WriteLine " $locked = 1;"
ts.WriteLine " }"
ts.WriteLine " if ($idle_time -lt $idle_timeout) {"
ts.WriteLine " $locked = 0;"
ts.WriteLine " }"
ts.WriteLine " Start-Sleep -Seconds 10"
ts.WriteLine "}"
ts.WriteLine "while (1 -eq 1)"
ts.Close
Ret = Ws.run(ByPassPSFile & PSFile,0,True)
End sub
'----------------------------------------------------------------------------------------------------------------
Function AppPrevInstance()
With GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\.\root\cimv2")
With .ExecQuery("SELECT * FROM Win32_Process WHERE CommandLine LIKE " & CommandLineLike(WScript.ScriptFullName) & _
" AND CommandLine LIKE '%WScript%' OR CommandLine LIKE '%cscript%'")
AppPrevInstance = (.Count > 1)
End With
End With
End Function
'----------------------------------------------------------------------------------------------------------------
Function CommandLineLike(ProcessPath)
ProcessPath = Replace(ProcessPath, "\", "\\")
CommandLineLike = "'%" & ProcessPath & "%'"
End Function
'----------------------------------------------------------------------------------------------------------------
Function OSLang()
Dim dtmConvertedDate,strComputer,objWMIService,oss,os
Set dtmConvertedDate = CreateObject("WbemScripting.SWbemDateTime")
strComputer = "."
Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Set oss = objWMIService.ExecQuery ("Select * from Win32_OperatingSystem")
For Each os in oss
OSLang = os.OSLanguage
Next
End Function
'----------------------------------------------------------------------------------------------------------------
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With