84

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?

3 Answers 3

77

GetLastInputInfo. Documented at PInvoke.net.

Sign up to request clarification or add additional context in comments.

2 Comments

+1 for PInvoke.net - I didn't know about that resource until now.
doesn't work for touch screens without mouse and keyboard activity
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.

3 Comments

You get the idle time in milliseconds, not ticks.
As kennyzx mention correct way to get timespan is TimeSpan timespent = TimeSpan.FromMilliseconds(ticks);
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?
-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;
    }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.