Search code examples
c#c#-4.0desktop-application

Windows system idle time calculations and total of time duration idle in c# code?


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.


Solution

  • First, you have two methods, GetIdleTime and GetLastInputTime. They are almost identical except that the former returns the idle time in milliseconds while the latter 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"));