SSzretter

how to detect user idle from system process or service?

13 posts in this topic

I have an autoit running as a windows service (as the SYSTEM user), and would like to detect whether the user is idle (no keyboard or mouse input).    I found in a normal script I can use " _Timer_GetIdleTime".  However, in my service / system user process the command does not work.     Has anyone figured out a way to determine user activity/inactivity from a different process, not running as the user?

Share this post


Link to post
Share on other sites



 

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.

1 person likes this

Share this post


Link to post
Share on other sites

What exactly does not work about it?

As far as I know only one use can be in control of mouse and keyboard at any one time, I'd not have thought it was user specific.

 

It always returns idle from a system service/process.

Share this post


Link to post
Share on other sites

How about using a slave background process running in user context?

 

That's exactly what I had to do, but I have found starting the process is not always reliable.  I  have had issues, for example when remote desktop is used, or fast user switching...   It's working most of the time, but I also do not like the fact that it's an extra process running...  I am just being picky and would love to have it all contained within one process.

Share this post


Link to post
Share on other sites

This thread is a bit dated, but I thought I'd add in case anyone needs to find out whether the system is idle.  Essentially, you can check the IO Reads from the process csrss.exe, session 1.

Global $lastIOReads, $currentIOReads
Global $MINUTES = 1000*60
Global $sleepTime = Round(1*$MINUTES,0)


pauseIfNotIdle()


Func pauseIfNotIdle()
        if $lastIOReads='' Then                                     ; checks to see if this is the first call of this function
            $lastIOReads = _getIOReads()                            ; sets initial value
            Sleep($sleepTime)                                       ; sleep, to look for idle
            $currentIOReads = _getIOReads()                         ; wake & check whether there has been any user input
        Else
            $lastIOReads = $currentIOReads                          ; not the first call, set last IO reads = the most recent
            $currentIOReads = _getIOReads()                         ; set IO reads to current
        EndIf

        While $lastIOReads<>$currentIOReads                         ; if there has been a change in the IO reads, do the loop
            Sleep($sleepTime)
            $lastIOReads = $currentIOReads                          ; set last IO reads = the most recent
            $currentIOReads = _getIOReads()                         ; set IO reads to current
        WEnd
EndFunc ; pauseIfNotIdle()


Func _getIOReads()
    Local $objWMIService = ObjGet("winmgmts:\root\CIMV2")
    Local $colItems = $objWMIService.ExecQuery('SELECT * FROM Win32_process where name="csrss.exe" and sessionId=1')    ; csrss is the Windows input exe; session 1 is console, which is the active session
    If IsObj($colItems) then                                                                                            ; csrss will change its IO Reads with input to the keyboard or mouse
      For $objItem In $colItems
       Return $objItem.ReadOperationCount                                                                               ; get IO reads
      Next
    Else
      Return False
    Endif
EndFunc ; getIOReads()

 

1 person likes this

Share this post


Link to post
Share on other sites

#9 ·  Posted (edited)

JohnOne, no: it appears the csrss / session 1 correlates ONLY to mouse & keyboard actions.  Just startup task manager and watch that process IO Reads without touching the mouse or keyboard. While csrss may have other responsibilities, it seems to correlate almost entirely with keyboard and mouse activity.  As an example, I logged into a remote PC I work with and took a snapshot of the IO Reads; 20-minutes later it's exactly the same value.

Edit: After ~2-hours the IO Reads remain the same on the PC referenced above.

Edited by bobmcrae
2 people like this

Share this post


Link to post
Share on other sites

@bobmcrae,

clever!!!

but you are checking only session 1. what if you are on a multi-user environment? that's not uncommon for home pc's, i imagine terminal servers should apply the same consideration. you must first enumerate all active sessions, and then check them all - they must all remain unchanged for the system to be considered idle. or am i missing something?

Share this post


Link to post
Share on other sites

orbs: You're right; in a multi-user environment to test for idle one would need to enumerate among the non-zero sessions.  However, in my case, I am interested in the user session that started my script; hence the need to just check session 1.

1 person likes this

Share this post


Link to post
Share on other sites

#13 ·  Posted

wow! Amazingly enough, this discussion saved me a lot of time and energy searching the web.

It seems the Windows10 Creators Update broke something in the behavior of GetLastInputInfo .

And even though this post has nothing to do with autoit (sorry mods), i just wanted to say a big thank you @bobmcrae for providing a strange, but perfectly working solution still working on Windows10 Creators Update.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now