Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get idle time of machine

Tags:

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?

like image 704
StrattonL Avatar asked Apr 06 '13 00:04

StrattonL


People also ask

What is machine idle time?

Idle time is paid time that an employee, or machine, is unproductive due to factors that can either be controlled or uncontrolled by management.

What are the 3 examples of idle time?

Examples of normal idle time include employee breaks, routine maintenance, and machine set-up time.

How is idle time accounted for?

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.


2 Answers

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)
}
like image 83
Andy Arismendi Avatar answered Oct 21 '22 00:10

Andy Arismendi


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
'----------------------------------------------------------------------------------------------------------------
like image 30
Hackoo Avatar answered Oct 20 '22 22:10

Hackoo