83

I'm writing a small tray application that needs to detect the last time a user interacted with their machine to determine if they're idle.

Is there any way to retrieve the time a user last moved their mouse, hit a key or interacted in any way with their machine?

I figure Windows obviously tracks this to determine when to display a screen saver or power down, etc, so I'm assuming there's a Windows API for retrieving this myself?

djdd87
  • 67,346
  • 27
  • 156
  • 195

3 Answers3

76

GetLastInputInfo. Documented at PInvoke.net.

Matthew Flaschen
  • 278,309
  • 50
  • 514
  • 539
59

include following namespaces

using System;
using System.Runtime.InteropServices;

and then include following

internal struct LASTINPUTINFO 
{
    public uint cbSize;

    public uint dwTime;
}

/// <summary>
/// Helps to find the idle time, (in milliseconds) spent since the last user input
/// </summary>
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);
    }
/// <summary>
/// Get the Last input time in milliseconds
/// </summary>
/// <returns></returns>
    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;
    }
}

To convert the tickcount into time you can use

TimeSpan timespent = TimeSpan.FromMilliseconds(ticks);

Note. This routine uses the term TickCount but the values are in milliseconds and are so not the same as Ticks.

From MSDN article on Environment.TickCount

Gets the number of milliseconds elapsed since the system started.

sgmoore
  • 15,694
  • 5
  • 43
  • 67
Sriwantha Attanayake
  • 7,694
  • 5
  • 42
  • 44
  • 21
    You get the idle time in milliseconds, not ticks. – kennyzx Sep 15 '12 at 17:47
  • 2
    As kennyzx mention correct way to get timespan is `TimeSpan timespent = TimeSpan.FromMilliseconds(ticks);` – Petr Jun 07 '16 at 20:16
  • When I create a class I cannot get any objects out of the class to set to a value, can you post an example of how you would use this after you instantiate the class? – Bbb Nov 06 '17 at 16:50
-1

Code:

 using System;
 using System.Runtime.InteropServices;

 public static int IdleTime() //In seconds
    {
        LASTINPUTINFO lastinputinfo = new LASTINPUTINFO();
        lastinputinfo.cbSize = Marshal.SizeOf(lastinputinfo);
        GetLastInputInfo(ref lastinputinfo);
        return (((Environment.TickCount & int.MaxValue) - (lastinputinfo.dwTime & int.MaxValue)) & int.MaxValue) / 1000;
    }