MH Rahman
MH Rahman

Reputation: 83

How to detect windows 10 user Idle status

I am working on an Windows Form that will run to Lock the Desktop after x minutes of User's inactivity.

I tried GetLastInputInfo() but it only detect the User's inactivity based on Keyboard and Mouse movement only. Well, it is written on their explanation (or do I misunderstand it?).

This function is useful for input idle detection. However, GetLastInputInfo does not provide system-wide user input information across all running sessions. Rather, GetLastInputInfo provides session-specific user input information for only the session that invoked the function.

*Now I understand the definition of system-wide user input, thanks to @Garr Godfrey

And now, I want to extend the functionality by detecting a running media player (From web browser or Window's media player).

For example:

My current Code is like this

    public class Form1 : Form
    {
        private struct LASTINPUTINFO
        {
            public uint cbSize;
            public uint dwTime;
        }

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

        public CancellationTokenSource ctsCheckInactive;
        public int InactivityCheckTimeGap = 1 * 1000;
        public int InactiveThresholdInS = 15 * 60 *1000; //15 minute

        public Form1()
        {
            InitializeComponent();
            CheckInactivity();
        }

        public void CheckInactivity()
        {
            ctsCheckInactive = new CancellationTokenSource();
            var t = System.Threading.Tasks.Task.Run(async () => await CheckInactivityRoutine(ctsCheckInactive.Token), ctsCheckInactive.Token);
        }

        private async Task CheckInactivityRoutine(CancellationToken ct)
        {
            while (true)
            {
                var time = GetLastInputTime();
                //Here I want to add Media Player Detection
                //if(DetectMediaPlayer() == true){
                //  time = 0
                //}
                
                //For debugging 
                Console.WriteLine(time + " Sec");

                If(time > InactiveThresholdInS){
                  //Lock the PC or show screen saver
                }

                ct.ThrowIfCancellationRequested();
                await System.Threading.Tasks.Task.Delay(InactivityCheckTimeGap);
            }
        }

        static uint GetLastInputTime()
        {
            uint idleTime = 0;
            LASTINPUTINFO lastInputInfo = new LASTINPUTINFO();
            lastInputInfo.cbSize = (uint)Marshal.SizeOf(lastInputInfo);
            lastInputInfo.dwTime = 0;

            //Gets the number of milliseconds elapsed since the system started.
            uint envTicks = (uint)Environment.TickCount;

            if (GetLastInputInfo(ref lastInputInfo))
            {
                uint lastInputTick = lastInputInfo.dwTime;
                idleTime = envTicks - lastInputTick;
            }

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

Does anyone know how to achieve that?

My program is minimized to windows tray and always running after the user logged in. And it has the ability like this.

Program on the system tray


EDIT: Added pseudo code

Upvotes: 0

Views: 3099

Answers (1)

Geoduck
Geoduck

Reputation: 8999

System wide user input reflects the fact that multiple users could be logged in to the same computer and have different desktops and sessions. Some users may be connected via Remote Desktop, or simply there could be multiple users logged in and you are switching between them.

Detecting media playing is problematic. You may be able to use one of the audio interfaces and measure output volume levels, but that's a major PITA. Detecting video is likely impossible (short of packet sniffing to look for packets coming from known streaming sites, hardly worthwhile or bullet proof).

Instead, why not implement a screen saver executable? The media programs disable screen savers while they run, and Windows handles launching it when it should. You can do a lot of stuff from the EXE itself. You could even use built in screensavers and just apply the setting to lock screen when resuming.

EDIT: A screensaver is really any executable file, renamed to be .scr. Windows will execute it based on the system screensaver settings. There are a few extra windows messages to handle, so I put examples in comments.

Upvotes: 1

Related Questions