如何检测PC上的用户活动/输入(或缺少)?

时间:2016-09-04 00:33:41

标签: powershell mouseevent keyboard-events

最近,我一直试图找到一种完全自动化备份系统的方法,该方法使用名为“AOMEI Backupper Standard”的第三方程序。我试图让计算机执行的自动序列包括:

  1. 每天中午前稍微打开电脑并在中午初始化一组两个增量备份,这将按顺序运行直到完成。这两个备份执行的总时间目前约为2小时55分钟(我有很多数据需要读取,即使有条带卷),但这个时间可能会随着我将来积累更多数据而增加。 / LI>
  2. 完成后,PC需要验证是否有人在任何重要时间段内(例如5分钟或更长时间内忽略快速使用或随机干扰)使用计算机,在此之前的一段时间内(例如1小时)第二次备份完成。或者,不是验证是否有超过5分钟的使用,PC可以简单地检测任何超过1分钟的使用(以消除键盘或鼠标被轻推或略微移动的随机错误)然后可能有另一个脚本如果用户希望PC在1小时的时间段内忽略其先前的使用情况,则重置使用标志。
  3. 如果在该时间段内没有重要的用户活动,那么PC必须在第二次备份结束时自动休眠(这样就完成了自动化过程,如果我不在家/使用PC)。否则,如果PC检测到此用户活动,则必须中止休眠,以便在我使用它时不会突然断电,或者我最近一直在使用它。
  4. 我可以使用批处理文件处理设置定时周期的开始,方法是先完成两次备份所需的时间,然后将其添加到正午,然后减去1小时。这将允许定时周期的开始相对于中午变得更晚,因为总备份时间随着存储更多数据而增加。

    因此,我正在寻找一种通过检查鼠标和/或键盘输入或通过其他方式在该时间段内检测PC上的用户活动的方法。这种检测方法还需要考虑是否已经设置了“ES_DISPLAY_REQUIRED”标志,或者类似,如果PC被用于观看长时间没有用户输入的电影,则不会被认为是空闲的。时间。

    除了直接检查M& K之外,我有一个想法用于检测,是以某种方式利用Windows空闲标志/状态,但修改它以忽略资源消耗作为确定空闲状态的因素。这是因为在备份期间,CPU和IO百分比空闲时间很容易低于Microsoft为Windows 8设置的80%阈值(有关详细信息,请参阅Microsoft的this page)(尽管我认为这也适用于Windows 10系统,这是我目前使用的操作系统),因此即使在此期间没有鼠标或键盘输入/用户存在,系统也永远不会“空闲”。

    理想情况下,我希望能够使用批处理文件/ Windows命令行(cmd)进行此检测,但我可以理解,这种类型的任务可能无法实现。因此,如果您对其他编程语言有任何建议可以与Windows集成/工作并且能够完成此任务,我很乐意听到它们(我有一些基本的HTML / CSS和JavaScript经验,以及作为Visual BASIC和命令行/批处理文件的中等水平的经验)。对不起,如果这有点过于冗长,但我想防止对我的问题产生任何疑惑。

    提前感谢您的时间。

    编辑#1 :我已经将标题概括为偏离我原来只使用批处理文件的选择,并且我为C#添加了一个标记,因为我知道它类似于VB和对于Windows中的任务非常有用。

    编辑#2 :在做了一些研究之后,我逐渐意识到PowerShell可能是另一个比批处理文件更强大的选项,因为它具有比cmd更高级的功能。现在,我将尝试对学习PowerShell进行一些研究并查看this one等相关问题,因为看起来我想要实现的目标可以在没有使用这种语言的大量复杂代码的情况下完成。

    编辑#3 :由于我不知道哪个可以解决我的问题,我似乎对多种语言的概括不被理解,所以我现在重新将问题重点放在PowerShell上。这是因为问题显然“与C#无关”,我现在几乎可以肯定它不能使用cmd完成,因为根本没有检测鼠标或键盘输入的命令。

1 个答案:

答案 0 :(得分:0)

this answer开始,您可以非常简单地在PowerShell中执行此操作。首先添加一个类型来访问Win32_UserInput类,然后您可以阅读创意时间。

当空闲时间满足您的要求并且您已完成时,只需触发您的操作即可。

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

P.S。上述代码采用人类可读的形式:

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

ForEach ($i in 0..9) {
    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)
}