如何确定C#应用程序中的空闲时间?

时间:2012-11-03 14:39:20

标签: c# .net

我想从我的应用程序中获取Windows空闲时间。我正在使用这段代码:

http://dataerror.blogspot.de/2005/02/detect-windows-idle-time.html

我在Windows 7上测试了它并且它运行正常,但我在Windows 8上只得到零。

任何想法如何解决这个问题?

3 个答案:

答案 0 :(得分:9)

我对您的方法采用了稍微不同的方法......这确定了应用程序的空闲时间,而不是使用系统范围的空闲时间。我不确定这是否符合您的需求,但它可能会帮助您进一步发展。它还具有纯.NET而不是DllImport的优点。

public partial class MyForm : Form, IMessageFilter {

    private Timer _timer;

    // we only need one of these methods...
    private DateTime _wentIdle;
    private int _idleTicks;

    public MyForm() {

        // watch for idle events and any message that might break idle
        Application.Idle += new EventHandler(Application_OnIdle);
        Application.AddMessageFilter(this);

        // use a simple timer to watch for the idle state
        _timer = new Timer();
        _timer.Tick += new EventHandler(Timer_Exipred);
        _timer.Interval = 1000;
        _timer.Start();

        InitializeComponent();
    }

    private void Timer_Exipred(object sender, EventArgs e) {
        TimeSpan diff = DateTime.Now - _wentIdle;

        // see if we have been idle longer than our configured value
        if (diff.TotalSeconds >= Settings.Default.IdleTimeout_Sec) {
            _statusLbl.Text = "We Are IDLE! - " + _wentIdle;
        }

        /**  OR  **/

        // see if we have gone idle based on our configured value
        if (++_idleTicks >= Settings.Default.IdleTimeout_Sec) {
            _statusLbl.Text = "We Are IDLE! - " + _idleTicks;
        }
    }

    private void Application_OnIdle(object sender, EventArgs e) {
        // keep track of the last time we went idle
        _wentIdle = DateTime.Now;
    }

    public bool PreFilterMessage(ref Message m) {
        // reset our last idle time if the message was user input
        if (isUserInput(m)) {
            _wentIdle = DateTime.MaxValue;
            _idleTicks = 0;

            _statusLbl.Text = "We Are NOT idle!";
        }

        return false;
    }

    private bool isUserInput(Message m) {
        // look for any message that was the result of user input
        if (m.Msg == 0x200) { return true; } // WM_MOUSEMOVE
        if (m.Msg == 0x020A) { return true; } // WM_MOUSEWHEEL
        if (m.Msg == 0x100) { return true; } // WM_KEYDOWN
        if (m.Msg == 0x101) { return true; } // WM_KEYUP

        // ... etc

        return false;
    }
}

我确实有两种确定空闲的方法......一种使用DateTime对象,一种使用简单的计数器。您可能会发现其中一个更适合您的需求。

有关您可能需要考虑作为用户输入的邮件列表,请访问here

答案 1 :(得分:1)

    protected override void OnLoad(EventArgs e)
    {
    /* Check if we are in idle mode - No mouse movement for 2 minutes */
    System.Windows.Forms.Timer CheckIdleTimer = new                    System.Windows.Forms.Timer();
    CheckIdleTimer.Interval = 120000;
    CheckIdleTimer.Tick += new EventHandler(CheckIdleTimer_Tick);
    CheckIdleTimer.Start();
    }
    private void CheckIdleTimer_Tick(object sender, EventArgs e)
    {
    uint x = IdleTimeFinder.GetIdleTime();
    if (x > 120000) {
         //...do something
    }
    }


    public class IdleTimeFinder
    {
    [DllImport("User32.dll")]
    private static extern bool GetLastInputInfo(ref LASTINPUTINFO plii);

    [DllImport("Kernel32.dll")]
    private static extern uint GetLastError();

    public static uint GetIdleTime()
    {
    LASTINPUTINFO lastInPut = new LASTINPUTINFO();
    lastInPut.cbSize     (uint)System.Runtime.InteropServices.Marshal.SizeOf(lastInPut);
    GetLastInputInfo(ref lastInPut);
    return ((uint)Environment.TickCount - lastInPut.dwTime);
    }

   public static long GetLastInputTime()
   {
    LASTINPUTINFO lastInPut = new LASTINPUTINFO();
    lastInPut.cbSize                (uint)System.Runtime.InteropServices.Marshal.SizeOf(lastInPut);
    if (!GetLastInputInfo(ref lastInPut))
    {
    throw new Exception(GetLastError().ToString());
    }
    return lastInPut.dwTime;
    }
    }


 internal struct LASTINPUTINFO
{
    public uint cbSize;

    public uint dwTime;
}

答案 2 :(得分:1)

这是示例代码,说明如何在Windows中检测空闲时间。空闲时间的定义是指没有与Windows的用户交互(例如没有键盘和鼠标输入)的时间。

检测闲置时间用于MSN Messenger等应用程序中,以便在用户未与Windows交互预定时间后将其状态更改为“ Away”。

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace GetLastInput_Demo
{
    /// <summary>
    /// Summary description for Form1.
    /// </summary>
    public class Form1 : System.Windows.Forms.Form
    {
        [DllImport("user32.dll")]
        static extern bool GetLastInputInfo(out LASTINPUTINFO plii);

        [StructLayout( LayoutKind.Sequential )]
        struct LASTINPUTINFO
        {
            public static readonly int SizeOf =
                   Marshal.SizeOf(typeof(LASTINPUTINFO));

            [MarshalAs(UnmanagedType.U4)]
            public int cbSize;   
            [MarshalAs(UnmanagedType.U4)]
            public int dwTime;
        }

        private System.Windows.Forms.Button button1;
        private System.Windows.Forms.Label label1;
        private System.Windows.Forms.Timer timer1;
        private System.ComponentModel.IContainer components;

        public Form1()
        {
            //
            // Required for Windows Form Designer support
            //
            InitializeComponent();

        }

        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        protected override void Dispose( bool disposing )
        {
            if( disposing )
            {
                if (components != null)
                {
                    components.Dispose();
                }
            }
            base.Dispose( disposing );
        }
        #region Windows Form Designer generated code
        private void InitializeComponent()
        {
            // Code is omitted here.
        }
        #endregion

        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.Run(new Form1());
        }

        private void button1_Click(object sender, System.EventArgs e)
        {
            timer1.Enabled = !timer1.Enabled;
        }

        private void timer1_Tick(object sender, System.EventArgs e)
        {
            int idleTime = 0;
            LASTINPUTINFO lastInputInfo = new LASTINPUTINFO();
            lastInputInfo.cbSize = Marshal.SizeOf( lastInputInfo );
            lastInputInfo.dwTime = 0;

            int envTicks = Environment.TickCount;

            if( GetLastInputInfo( out lastInputInfo ) )
            {
                int lastInputTick = lastInputInfo.dwTime;
                idleTime = envTicks - lastInputTick;
            }

            int a;
           
            if(idleTime > 0)
               a = idleTime / 1000;
            else
               a = idleTime;

            label1.Text = a.ToString();
        }
    }
}