【问题标题】:Get idle time of machine获取机器空闲时间
【发布时间】:2013-04-06 00:08:31
【问题描述】:

有没有办法使用 Powershell 或批处理文件来获取机器的空闲时间,例如机器未使用的时间,以分钟/小时为单位?

【问题讨论】:

  • 更准确地定义“未用于”。自从它被注销后?屏幕保护程序打开了多长时间?究竟是什么?
  • 我似乎无法在这个网站上做任何事情......碰巧,下面的答案正是我正在寻找的 - 从用户停止移动鼠标点开始的空闲时间或按键盘上的按钮。
  • 不知道为什么有人对你投了反对票,也许这个问题有点含糊,或者没有显示你是否尝试过任何东西......请务必查看how to ask

标签: powershell


【解决方案1】:

这是一个使用 Win32 API GetLastInputInfo 的 PowerShell 解决方案。

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;
            }
        }
    }
}
'@

还有一个用法示例:

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)
}

【讨论】:

  • 非常感谢!正是我正在寻找的。如何格式化输出以使其更具可读性 - 即 4 小时 15 分钟 21 秒?再次感谢!
  • 这是一个很好的实现,可以在一段时间后锁定计算机:gist.github.com/wendelb/1c364bb1a36ca5916ca4
  • 这似乎不适用于远程机器;我认为它只会为当前用户会话提供空闲时间。
  • 伙计,这太棒了....关于如何使它在远程机器上工作,从一个计划任务运行它,该任务以当前登录用户的身份运行代码(谷歌如何做到这一点)
  • 谢谢。它帮助我发现了一个尘土飞扬的触摸板可以为系统生成输入,并保持显示。
【解决方案2】:

此 vbscript 代码的灵感来自已回答的问题,旨在向您展示我们如何使用它在空闲超时后自动关闭您的工作站!

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
'----------------------------------------------------------------------------------------------------------------

【讨论】:

  • 您使用 VB 而不是全部在 PS 中做这件事有什么特别的原因吗?
【解决方案3】:
$Last = [PInvoke.Win32.UserInput]::LastInput
$Idle = [PInvoke.Win32.UserInput]::IdleTime
$LastStr = $Last.ToLocalTime().ToString("MM/dd/yyyy hh:mm tt")
Write-Host ("Last user keyboard/mouse input: " + $LastStr)
Write-Host ("Idle for " + $Idle.Days + " days, " + $Idle.Hours + " hours, " + $Idle.Minutes + " minutes, " + $Idle.Seconds + " seconds.")

试试这个 - 虽然远程运行它可能在不同的会话上运行,因此有不同的空闲时间?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-24
    • 2011-09-23
    • 1970-01-01
    • 2012-08-09
    • 2019-01-17
    • 1970-01-01
    相关资源
    最近更新 更多