1

Developed windows application for user activity process. need to calculate how much time user did not use system and how much time used system for working performance using c# application. I am using follow the code but did not receive correct value of idle time and duration time. Can any one please help me how to solve this problem.

       public class clsAttendance
       {        
        int _IdleCount = 0;
       

        [DllImport("user32.dll")]
        static extern bool GetLastInputInfo(ref LASTINPUTINFO plii);

        public clsAttendance()
        {
            _clsData = new clsDataConnection();
        }    


        public 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 uint GetLastInputTime()
        {
            uint idleTime = 0;
            LASTINPUTINFO lastInputInfo = new LASTINPUTINFO();
            lastInputInfo.cbSize = (uint)Marshal.SizeOf(lastInputInfo);
            lastInputInfo.dwTime = 0;

            uint envTicks = (uint)Environment.TickCount;

            if (GetLastInputInfo(ref lastInputInfo))
            {
                uint lastInputTick = lastInputInfo.dwTime;

                idleTime = envTicks - lastInputTick;
            }

            return ((idleTime > 0) ? (idleTime / 1000) : 0);
        }
               
    }

    internal struct LASTINPUTINFO
    {
        public uint cbSize;

        public uint dwTime;
    }


private void Form1_Load(object sender, EventArgs e)
        {
     a = new Timer();
         a.Tick += A_Tick;
         a.Interval = 10 * 60 * 1000;
         a.Start();

    }

 private void A_Tick(object sender, EventArgs e)
        {         

            ExceptionLogger.WriteErrorLog($"Current time: {DateTimeOffset.Now}");

            ExceptionLogger.WriteErrorLog($"Last input time without timespan: {  clsSystemIdle.GetLastInputTime()}");

            ExceptionLogger.WriteErrorLog($"Idle time without timespan: {_clsAtt.GetIdleTime()}");

            ExceptionLogger.WriteErrorLog(Message: $"Last Input TimeSpan Minutes : {TimeSpan.FromMilliseconds(clsSystemIdle.GetLastInputTime())}");

            ExceptionLogger.WriteErrorLog(Message: $"Idle TimeSpan Minutes : {TimeSpan.FromMilliseconds(_clsAtt.GetIdleTime())}");

        }

Last 40 minutes not using keyboard and mouse, then returned output below,

Current time: 3/4/2022 1:49:59 PM +05:30 Last input time without timespan: 125 Idle time without timespan: 125266 Last Input TimeSpan : 00:00:00.1250000 Idle TimeSpan : 00:02:05.3440000

Current time: 3/4/2022 1:59:59 PM +05:30 Last input time without timespan: 22 Idle time without timespan: 22203 Last Input TimeSpan : 00:00:00.0220000 Idle TimeSpan : 00:00:22.2810000

Current time: 3/4/2022 2:09:59 PM +05:30 Last input time without timespan: 101 Idle time without timespan: 101329 Last Input TimeSpan : 00:00:00.1010000 Idle TimeSpan : 00:01:41.4380000

Current time: 3/4/2022 2:19:59 PM +05:30 Last input time without timespan: 3 Idle time without timespan: 3172 Last Input TimeSpan : 00:00:00.0030000 Idle TimeSpan : 00:00:03.1720000

Here I want last 40 minutes system idle, but how to get 40 minutes value from above returned values and print exception log file. Please tell me how to solve this task.

George
  • 13
  • 6
  • define *correct* or not. – Lei Yang Mar 02 '22 at 08:32
  • working fine, but returned value changed every time when a timer tick. once return 2 min and another time return 0 like it. I want user 30 minutes long did not use keyboard and mouse then write a txt file date and time with idle time duration. Please help me – George Mar 02 '22 at 10:35
  • `TimeSpan.FromMinutes` ? See: https://stackoverflow.com/a/11901730/14171304 – dr.null Mar 02 '22 at 10:54
  • Thanks for your Help, I am using your code only return values are following attached here, When system Idle. I do not know whish time idle and working time. Please suggest me – George Mar 03 '22 at 09:26
  • 3/3/2022 2:45:48 PM: Last Input TimeSpan Minutes : 00:00:00 3/3/2022 2:45:49 PM: Idle TimeSpan Minutes : 00:16:00 Current time: 3/3/2022 2:45:49 PM +05:30 Last input time without timespan: 0 Idle time without timespan: 0 – George Mar 03 '22 at 09:27
  • I don't know what you need. Edit your question to add an example for the inputs and expected outputs. `Environment.TickCount - plii.dwTime` does not return minutes so you can't create a TimeSpan from minutes. You should `TimeSpan.FromMilliseconds(...)`. – dr.null Mar 03 '22 at 13:32
  • sir, again edit my working code and output values, please check and suggest me how to this. Once again thanks to your valuable reply. – George Mar 04 '22 at 09:15

1 Answers1

0

First, you have two methods, GetIdleTime and GetLastInputTime. They are almost identical except that the former returns the idle time in milliseconds while the later returns it in seconds by idleTime / 1000. You just need the following to get the idle time.

public class SomeClass
{
    public static uint GetIdleTime()
    {
        var info = new LASTINPUTINFO();

        info.cbSize = (uint)Marshal.SizeOf(info);

        return GetLastInputInfo(ref info)
            ? (uint)Environment.TickCount - info.dwTime
            : 0;
    }

    [StructLayout(LayoutKind.Sequential)]
    struct LASTINPUTINFO
    {
        [MarshalAs(UnmanagedType.U4)]
        public uint cbSize;
        [MarshalAs(UnmanagedType.U4)]
        public uint dwTime;
    }

    [DllImport("user32.dll")]
    private static extern bool GetLastInputInfo(ref LASTINPUTINFO plii);
}

Second, you've said:

Last 40 minutes not using keyboard and mouse, then returned output below...

From your test results, this is not accurate because the idle time is not incrementing as it should. (you have 125266, 22203, 101329, and 3172 respectively) which means breaking the user-idle state multiple times during that duration by an input device or code. Otherwise, the GetIdleTime method should return 2,400,000 milliseconds (40 minutes).

Third, consider the following code snippets.

// Get and print the idle time in milliseconds...
var it = SomeClass.GetIdleTime();
Console.WriteLine(it);

// Create and print a TimeSpan...
var itTimeSpan = TimeSpan.FromMilliseconds(it)
Console.WriteLine(itTimeSpan.ToString("hh\\:mm\\:ss"));

// Get and print the last input DateTime...
var lastInputTime = DateTime.Now.AddMilliseconds(-it); // Or DateTimeOffset...
Console.WriteLine(lastInputTime);
// Or
Console.WriteLine(lastInputTime.ToString("hh:mm:ss"));
dr.null
  • 4,032
  • 3
  • 9
  • 12
  • Sir its working fine. but how to track continuous idle time tracking. Using Timer or Thread. – George Mar 05 '22 at 11:18
  • @George Keep the value that you get from `SomeClass.GetIdleTime()` in a class variable of `uint` type say `lastIdleTime`. When you get the idle time next time in the `Timer.Tick` event, compare it with `lastIdleTime`. Less value means no continuation and the system has exited the user-idle state at least once. Of course `0` means no idle state. – dr.null Mar 05 '22 at 11:54