Jump to content

Get Idle Time for a specific application window (and child windows with different titles) - (Moved)


Recommended Posts

Hello,

Background: we run an application that started in the 1980s written by programmers who (I believe) learned to code by trial and error. The company that owns the application does do updates but only to add functionality. They ported it to .NET from C+ (yippee) a couple years ago to make it 32 bit and the biggest announcement in April was that they will start compiling a 64 bit version. It has to run installed on the workstation but we have to guarantee it shuts down every night since there is a batch file to update the application on each workstation and then launch it again. I have a file server share that I update as I make changes to reports or application functionality and then users have to re-launch the application. It's crazy but we're stuck since no one else has any options that meet our needs.

I was able to figure out how to at least guarantee it is shut down every night when no one is here.

#NoTrayIcon
#include <Timers.au3>
#include <Misc.au3> ; needed for _Singleton
#include <Date.au3> ; needed to read system time

; ensure this script is only run once. If you change the name of your script you should change this to match.
If _Singleton("DFLChamCleanup", 1) = 0 Then
   Exit
EndIf

;$TimerInterval = 1 * 60 * 1000 ; 1 minute testing line
$TimerInterval = 8 * 60 * 1000 ; 8 minutes

;Close Chameleon between these times in the morning regardless of activity.
$StartTime = "0300"
$EndTime = "0310"

;Loop:
While 1
   If Not ProcessExists("Chameleon.exe") Then Exit

   $CurrentTime = @HOUR & @MIN
   If $CurrentTime <= $EndTime and $CurrentTime >= $StartTime Then
      ProcessClose("Chameleon.exe")
      ContinueLoop
   EndIf

   If _Timer_GetIdleTime() >= $TimerInterval Then
      Do
         SplashTextOn("Timeout Reached", "Chameleon has been idle for longer than 8 minutes." _
                        & @CRLF & @CRLF & "Chameleon will be shut down in the next 2 minutes." _
                        & @CRLF & @CRLF & "Any unsaved work will be lost!")

         Sleep(2 * 60 * 1000) ; 2 minutes idle time after notification

         If _Timer_GetIdleTime() < $TimerInterval Then
            SplashOff()
            ContinueLoop
         EndIf

         ProcessClose("Chameleon.exe")

         SplashOff()

      Until _Timer_GetIdleTime() < $TimerInterval or Not ProcessExists("Chameleon.exe")
   EndIf

   ;Sleep for 15 seconds:
   Sleep(15 * 1000)
WEnd

Now, I need to modify this so it will also shut down the application after 10 minutes of inactivity in just that application. This code works if I leave the workstation alone but that is not the desired solution as it is looking at overall system idle time. Users frequently switch between this application and our SSRS environment that I also design and maintain. The examples that I found that have gotten me this far have been great. However, I can't seem to find anything to get the idle time of a specific application and it's child windows. I also found examples to return the window state but I can't find a reference to tell me what ALL of the return values are (note below that I got a 3 at one point and the help file doesn't list a 3 or 15 and 7 for that matter).

Opt("WinTitleMatchMode", 1) ;1 = Start of String
Opt("TrayIconDebug", 1)

$title = "[REGEXPTITLE:(?i)(.*Chameleon 32.*)]"   ; "PayDay is the title of the site"
$count = 0
While 1
    $state = WinGetState("[REGEXPTITLE:(?i)(.*Chameleon 32.*)]")
    $count += 1

    If $state = 15 Or $state = 47 Or $state = 0 Then $count = 0

    If $count > 30 Then WinClose($title)  ;close after idling for 10 seconds

    ToolTip("count = " & $count, 0, 0, "state = " & $state)
    Sleep(1000)    ; reloop in 1 sec
WEnd

When the main "parent" window has focus, the state is 15 and count stays at 0. When it loses focus (I click in another application), the state is 7 and the counter starts incrementing by 1. I can derive from those results that 15 means the window has focus and 7 means it doesn't have focus. When the parent window opens a child window however, the state changes to 3 and the counter starts counting even if I'm doing something in the child window. To further complicate things, the child windows all have different window titles. It's easy enough to get a list of the different window titles as there are only 20 some odd child windows. I can't say I'm understanding much of the second snippet of code but I'm more than comfortable working from examples to come up with a final solution. Perhaps something that loops through an array of the window titles to see if any of them are idle actively receiving keystrokes and/or mouse clicks?

Any and all help will be greatly appreciated.

Link to comment
Share on other sites

A basic method of getting the idle time is check the mouse movement and when movement = true then reset counter, else, count.

For a specific application, maybe you can mess around with window handles too, and classes.

Then go from there, so if what you want is to reset the counter if the user is working in any of the child windows or parent, if the class is common, maybe use it, find something that's common to all windows that you want to check and count/reset counter, that's my 2 cents.

 

Ps: https://www.autoitscript.com/autoit3/docs/functions/WinGetState.htm

either 7 or 15 is the combination of multiple states.

Edited by careca
Spoiler

Renamer - Rename files and folders, remove portions of text from the filename etc.

GPO Tool - Export/Import Group policy settings.

MirrorDir - Synchronize/Backup/Mirror Folders

BeatsPlayer - Music player.

Params Tool - Right click an exe to see it's parameters or execute them.

String Trigger - Triggers pasting text or applications or internet links on specific strings.

Inconspicuous - Hide files in plain sight, not fully encrypted.

Regedit Control - Registry browsing history, quickly jump into any saved key.

Time4Shutdown - Write the time for shutdown in minutes.

Power Profiles Tool - Set a profile as active, delete, duplicate, export and import.

Finished Task Shutdown - Shuts down pc when specified window/Wndl/process closes.

NetworkSpeedShutdown - Shuts down pc if download speed goes under "X" Kb/s.

IUIAutomation - Topic with framework and examples

Au3Record.exe

Link to comment
Share on other sites

  • Moderators

Moved to the appropriate forum, as the Developer General Discussion forum very clearly states:

Quote

General development and scripting discussions. If it's super geeky and you don't know where to put it - it's probably here.


Do not create AutoIt-related topics here, use the AutoIt General Help and Support or AutoIt Technical Discussion forums.

Moderation Team

"Profanity is the last vestige of the feeble mind. For the man who cannot express himself forcibly through intellect must do so through shock and awe" - Spencer W. Kimball

How to get your question answered on this forum!

Link to comment
Share on other sites

can you impose the application i question be minimized when not worked upon? if so, it should be rather simple to time. as for child windows, it is common that while these appear, the main window still appears in the background (not minimized).

Signature - my forum contributions:

Spoiler

UDF:

LFN - support for long file names (over 260 characters)

InputImpose - impose valid characters in an input control

TimeConvert - convert UTC to/from local time and/or reformat the string representation

AMF - accept multiple files from Windows Explorer context menu

DateDuration -  literal description of the difference between given dates

Apps:

Touch - set the "modified" timestamp of a file to current time

Show For Files - tray menu to show/hide files extensions, hidden & system files, and selection checkboxes

SPDiff - Single-Pane Text Diff

 

Link to comment
Share on other sites

1 hour ago, orbs said:

can you impose the application i question be minimized when not worked upon? if so, it should be rather simple to time. as for child windows, it is common that while these appear, the main window still appears in the background (not minimized).

I could have a requirement that users minimize the application and child windows when not in use but we are talking about users.

17 hours ago, careca said:

A basic method of getting the idle time is check the mouse movement and when movement = true then reset counter, else, count.

For a specific application, maybe you can mess around with window handles too, and classes.

Then go from there, so if what you want is to reset the counter if the user is working in any of the child windows or parent, if the class is common, maybe use it, find something that's common to all windows that you want to check and count/reset counter, that's my 2 cents.

 

Ps: https://www.autoitscript.com/autoit3/docs/functions/WinGetState.htm

either 7 or 15 is the combination of multiple states.

You'll have to forgive me on the window states. I have looked at the help document but I'm not understanding the "combination" of multiple states. Is it implying that adding all of these ($WIN_STATE_EXISTS (1) = Window exists, $WIN_STATE_VISIBLE (2) = Window is visible, $WIN_STATE_ENABLED (4) = Window is enabled, $WIN_STATE_ACTIVE (8) = Window is active) is how it came up with 15? Then 7 is a combination of ($WIN_STATE_EXISTS (1) = Window exists, $WIN_STATE_VISIBLE (2) = Window is visible, $WIN_STATE_ENABLED (4) = Window is enabled) and 3 is a combination of ($WIN_STATE_EXISTS (1) = Window exists, $WIN_STATE_VISIBLE (2) = Window is visible)?

Here is what I thought about last night. I could have it go through every possible window title and if it finds a 15, then it looks at overall system idle time to determine the 10 minute timeout. However, if the state is anything different, meaning the user is in another application, I count the seconds I don't have at least one window in a state of 15?

Link to comment
Share on other sites

Yes, thats it.

That is a doable thing, and even if no window is in a 15 state, you can then check mouse movement for example.

Doesn't have to be 15 you know? you can check for whatever suits what you need to check, if it's only "window exists", it's 1, for example, but you get the idea.

Spoiler

Renamer - Rename files and folders, remove portions of text from the filename etc.

GPO Tool - Export/Import Group policy settings.

MirrorDir - Synchronize/Backup/Mirror Folders

BeatsPlayer - Music player.

Params Tool - Right click an exe to see it's parameters or execute them.

String Trigger - Triggers pasting text or applications or internet links on specific strings.

Inconspicuous - Hide files in plain sight, not fully encrypted.

Regedit Control - Registry browsing history, quickly jump into any saved key.

Time4Shutdown - Write the time for shutdown in minutes.

Power Profiles Tool - Set a profile as active, delete, duplicate, export and import.

Finished Task Shutdown - Shuts down pc when specified window/Wndl/process closes.

NetworkSpeedShutdown - Shuts down pc if download speed goes under "X" Kb/s.

IUIAutomation - Topic with framework and examples

Au3Record.exe

Link to comment
Share on other sites

After a few iterations of different combinations, I finally have something that is working as expected. Let me know if there is anything you would change or if this looks as optimized as it is going to get. Database programming is easy! This had me tripped up for a couple of days.

#NoTrayIcon
#include <Array.au3>
#include <Date.au3> ; needed to read system time
#include <Misc.au3> ; needed for _Singleton
#include <Timers.au3> ; needed to read system idle time

; ensure this script is only run once. If you change the name of your script you should change this to match.
If _Singleton("DFLChamCleanup", 1) = 0 Then
    Exit
EndIf

Opt("WinTitleMatchMode", 2) ;1 = Start of String, 2 = Match any substring in the title.
Opt("TrayIconDebug", 1)

$TimerInterval = 1 * 60 * 1000 ; 1 minute testing line
;$TimerInterval = 8 * 60 * 1000 ; 8 minutes

$SecondsInactiveWindowIsIdle = 60 ; 1 minute testing line
;$SecondsInactiveWindowIsIdle = 480 ; 8 minutes

;Close Chameleon between these times in the morning regardless of activity.
$StartTime = "0300"
$EndTime = "0310"

; Array list of all possible windows. Using the option to match on start of string above
; keeps this list shorter than a complete list of all windows.
Global $WinList[33]
$WinList[0] = "Chameleon 32"
$WinList[1] = "Activity"
$WinList[2] = "Adopter"
$WinList[3] = "Adoption"
$WinList[4] = "Animal"
$WinList[5] = "Attendance"
$WinList[6] = "Behavior"
$WinList[7] = "Bite"
$WinList[8] = "Certification"
$WinList[9] = "Citation"
$WinList[10] = "Close of Business"
$WinList[11] = "Contact"
$WinList[12] = "Cost Center"
$WinList[13] = "Deposit"
$WinList[14] = "Dispatch"
$WinList[15] = "Donation"
$WinList[16] = "Donor"
$WinList[17] = "Evaluation"
$WinList[18] = "Group"
$WinList[19] = "Inventory"
$WinList[20] = "Kennel"
$WinList[21] = "Member"
$WinList[22] = "Memo"
$WinList[23] = "Person"
$WinList[24] = "Preferences"
$WinList[25] = "Receipt"
$WinList[26] = "Requisition"
$WinList[27] = "Shift"
$WinList[28] = "Tag"
$WinList[29] = "To Do"
$WinList[30] = "Training"
$WinList[31] = "Treatment"
$WinList[32] = "Volunteer"

$Seconds = 0

;Loop:
While 1
    ; Don't run if Chameleon is not already running.
    If Not ProcessExists("Chameleon.exe") Then
        Exit
    EndIf

    ; If Chameleon is running between the times listed above, close it.
    $CurrentTime = @HOUR & @MIN
    If $CurrentTime <= $EndTime and $CurrentTime >= $StartTime Then
        ProcessClose("Chameleon.exe")
        ContinueLoop
    EndIf

    $ActiveWindowFound = 0 ; Used to determine whether or not we found an active window.
    For $i = 0 To 32 ; Loop through the window list to see if the window is active.
        $State = WinGetState($WinList[$i])

        If $State = 15 Or $State = 47 Then ; 15 = Window is active, 47 = Window is active and maximized.
            $ActiveWindowFound = 1
            $Seconds = 0
            If _Timer_GetIdleTime() >= $TimerInterval Then ; Check to see if system idle time is greater than threshold defined above. If it is, show the message.
                Do
                    SplashTextOn("Chameleon Timeout Reached", "Chameleon has been idle for longer than 8 minutes." _
                                  & @CRLF & @CRLF & "Chameleon will be shut down in the next 2 minutes." _
                                  & @CRLF & @CRLF & "Any unsaved work will be lost!", 500, 250, -1, -1, -1, "", 20, 900)

                    $SecondCounter = 0
                    Do ; This loop checks for the idle time to reset. If it resets, exit to the parent loop and start over.
                        If _Timer_GetIdleTime() < $TimerInterval Then
                            SplashOff()
                            ContinueLoop 2 ; Exits to the For loop to start looking through the windows again.
                        EndIf

                        $SecondCounter += 1
                        Sleep(1000)
                    Until $SecondCounter > 120 ; Continues checking for idle time for two minutes before shutting down Chameleon.

                    SplashOff()
                    ProcessClose("Chameleon.exe")
                    Sleep(10 * 1000) ; Give Chameleon ten seconds to close before hitting the end of the loop. This insures that the splash text stays off.

                Until _Timer_GetIdleTime() < $TimerInterval or Not ProcessExists("Chameleon.exe")
            EndIf
        EndIf

        If $ActiveWindowFound = 1 Then ; If we found an active window, stop looking at windows.
            ExitLoop
        EndIf
    Next

    If $Seconds >= $SecondsInactiveWindowIsIdle Then ; Check to see if the number of seconds Chameleon has not been active is greater than threshold defined above.
        Do
            SplashTextOn("Chameleon Timeout Reached", "Chameleon has been idle for longer than 8 minutes." _
                          & @CRLF & @CRLF & "Chameleon will be shut down in the next 2 minutes." _
                          & @CRLF & @CRLF & "Any unsaved work will be lost!", 500, 250, -1, -1, -1, "", 20, 900)

            $SecondCounter = 0
            Do
                For $i = 0 To 32 ; Loop through the window list to see if a window has become active. If one has become active, reset seconds inactive counter.
                    $State = WinGetState($WinList[$i])
                        If $State = 15 Or $State = 47 Then
                            $Seconds = 0
                        EndIf
                Next

                If $Seconds < $SecondsInactiveWindowIsIdle Then
                    SplashOff()
                    ContinueLoop 2
                EndIf

                $SecondCounter += 1
                Sleep(1000)
            Until $SecondCounter > 120

            SplashOff()
            ProcessClose("Chameleon.exe")
            Sleep(10 * 1000) ; Give Chameleon ten seconds to close before hitting the end of the loop. This insures that the splash text stays off.

        Until $Seconds < $SecondsInactiveWindowIsIdle or Not ProcessExists("Chameleon.exe")
    EndIf

    $Seconds += 1
    ;ToolTip("count = " & $Seconds, 0, 0, "state = " & $state) ; Used for troubleshooting. Leave commented out for normal execution.

    Sleep(1000) ; reloop in 1 sec
WEnd

 

Link to comment
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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...