jaycee73

Auto Close Idle Application

7 posts in this topic

#1 ·  Posted

Hi all,

 

I'm using the below script (that I found elsewhere and modified) to detect an idle application and auto logoff if it has been idle for a certain amount of time. It works perfectly when there is only one instance of the application open, but what I would like, if possible, is if it can also detect a second instance that is idle in the background while a user is actively using the first instance - at the moment if one instance is active then the second, idle instance, is not closed. Both instances of my application have identical titles.

 

Thanks in advance for any assistance,

John

 

 

#cs ----------------------------------------------------------------------------

 AutoIt Version: 3.3.14.2
 Author:         

 Script Function:
    Auto logs out inactive applicationXXX Sessions

#ce ----------------------------------------------------------------------------

; Script Start - Add your code below here
Opt("WinTitleMatchMode", 2) ;3 = exact title match
Opt("TrayIconDebug", 1)

; Opt("TrayIconHide", 1)


$S_running = "check-4-app" ;name the script
If WinExists($S_running) Then Exit
AutoItWinSetTitle($S_running)

$title = "applicationXXX"
$count = 0
While 1
    $state = WinGetState($title)
    $count += 1

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

    If $count > 20 Then WinClose($title)

    ToolTip("count = " & $count, 0, 0, "state = " & $state)
    Sleep(1000)
WEnd

Share this post


Link to post
Share on other sites



#4 ·  Posted

Thanks for your responses JohnOne and Juvigy. Unfortunately, I'm not a programmer (just a bit of a hack) so don't have the skills to rewrite the script from scratch.

 

Any other advice would be appreciated.

 

Cheers,

Jaycee

Share this post


Link to post
Share on other sites

#5 ·  Posted

On 3/10/2017 at 4:15 AM, JohnOne said:

Well for a start, you should work with handles rather than titles.

But first, define "Idle Application"

In this instance, the application window has not been interacted with in x amount of time (i.e. the user is either away from their desk, or busy using a different application.

 

Cheers,

Jaycee

Share this post


Link to post
Share on other sites

#6 ·  Posted (edited)

#include <Array.au3>

Opt("WinTitleMatchMode", 2) ;3 = exact title match
Opt("TrayIconDebug", 1)

; Opt("TrayIconHide", 1)

Global Const $ARRAY_HANDLE = 0
Global Const $ARRAY_PID = 1
Global Const $ARRAY_COUNT = 2
Global Const $WINLIST_TITLE = 0
Global Const $WINLIST_HANDLE = 1

Global $aWindows[0][3]

For $i = 0 to 3
    Run("notepad.exe", @SystemDir)
Next

$title = "Untitled - Notepad"
$S_running = "check-4-app" ;name the script

UpdateWithHandles($aWindows, $title)

If WinExists($S_running) Then Exit
AutoItWinSetTitle($S_running)

While (True)
    Local $sToolTip = ""
    For $i = UBound($aWindows) -1 to 0 Step -1
        $state = WinGetState($aWindows[$i][$ARRAY_HANDLE])
        $aWindows[$i][$ARRAY_COUNT] += 1

        If ($state = 15 Or $state = 47 Or $state = 0 Or $state = 3 Or $state = 7) Then
            $aWindows[$i][$ARRAY_COUNT] = 0
        EndIf

        If ($aWindows[$i][$ARRAY_COUNT] > 20) Then WinClose($aWindows[$i][$ARRAY_HANDLE])

        $sToolTip &= $aWindows[$i][$ARRAY_HANDLE] & ":" & @CRLF & @TAB & "Count = " & $aWindows[$i][$ARRAY_COUNT] & @CRLF & @TAB & "State = " & $state & @CRLF
    Next
    ToolTip(StringTrimRight($sToolTip, 2), 0, 0)
    Sleep(1000)
    UpdateWithHandles($aWindows, $title)
WEnd

Func UpdateWithHandles(ByRef $aArray, Const ByRef $sWindowTitle)
    Local $aWinList = WinList()

    ; My personal preference, hate having the count in the first element of an array, so I remove it
    _ArrayDelete($aWinList, 0)

    If (UBound($aArray)) Then
        ; First check that the window still exists, if it doesn't then remove it
        For $iProcess = UBound($aArray) - 1 to 0 Step - 1
            If (Not WinExists($aArray[$iProcess][$ARRAY_HANDLE])) Then
                ; Window no longer exists, remove from the array
                _ArrayDelete($aArray, $iProcess)
            EndIf
        Next
    EndIf

    For $iProcess = 0 To UBound($aWinList) -1
        Local $iPid = 0
        Local $iIndex = 0
        
        ; Title of this window is the title we're looking for
        If ($aWinList[$iProcess][$WINLIST_TITLE] = $sWindowTitle) Then
            ; I used PID but you can use the handle, just wanted to throw PID in this script
            $iPid = WinGetProcess($aWinList[$iProcess][$WINLIST_HANDLE])

            If (_ArraySearch($aArray, $iPid, 0, 0, 0, 0, 1, $ARRAY_PID) = -1) Then
                ; Store the current index so we don't have to use UBound 4 times
                $iIndex = UBound($aArray)

                ; Redim the array so we can add the new handle, PID, and count
                ReDim $aArray[$iIndex + 1][UBound($aArray, $UBOUND_COLUMNS)]

                ; Add values
                $aArray[$iIndex][$ARRAY_HANDLE] = $aWinList[$iProcess][$WINLIST_HANDLE]
                $aArray[$iIndex][$ARRAY_PID] = $iPid
                $aArray[$iIndex][$ARRAY_COUNT] = 0
            EndIf
        EndIf
    Next
EndFunc

Give that a go. I cleaned up some of the code, not all. You should rework the state checking to only reset to 0 when the window is visible and active. This can be more easily accomplished using BitAND

If (BitAND($state, 8) and BitAND($state, 2)) Then
    ...
EndIf

It's up to you how you want to determine if a window is inactive though, just my preference.

Edited by InunoTaishou
Added some more comments

Share this post


Link to post
Share on other sites

#7 ·  Posted

On 3/23/2017 at 0:01 PM, InunoTaishou said:
#include <Array.au3>

Opt("WinTitleMatchMode", 2) ;3 = exact title match
Opt("TrayIconDebug", 1)

; Opt("TrayIconHide", 1)

Global Const $ARRAY_HANDLE = 0
Global Const $ARRAY_PID = 1
Global Const $ARRAY_COUNT = 2
Global Const $WINLIST_TITLE = 0
Global Const $WINLIST_HANDLE = 1

Global $aWindows[0][3]

For $i = 0 to 3
    Run("notepad.exe", @SystemDir)
Next

$title = "Untitled - Notepad"
$S_running = "check-4-app" ;name the script

UpdateWithHandles($aWindows, $title)

If WinExists($S_running) Then Exit
AutoItWinSetTitle($S_running)

While (True)
    Local $sToolTip = ""
    For $i = UBound($aWindows) -1 to 0 Step -1
        $state = WinGetState($aWindows[$i][$ARRAY_HANDLE])
        $aWindows[$i][$ARRAY_COUNT] += 1

        If ($state = 15 Or $state = 47 Or $state = 0 Or $state = 3 Or $state = 7) Then
            $aWindows[$i][$ARRAY_COUNT] = 0
        EndIf

        If ($aWindows[$i][$ARRAY_COUNT] > 20) Then WinClose($aWindows[$i][$ARRAY_HANDLE])

        $sToolTip &= $aWindows[$i][$ARRAY_HANDLE] & ":" & @CRLF & @TAB & "Count = " & $aWindows[$i][$ARRAY_COUNT] & @CRLF & @TAB & "State = " & $state & @CRLF
    Next
    ToolTip(StringTrimRight($sToolTip, 2), 0, 0)
    Sleep(1000)
    UpdateWithHandles($aWindows, $title)
WEnd

Func UpdateWithHandles(ByRef $aArray, Const ByRef $sWindowTitle)
    Local $aWinList = WinList()

    ; My personal preference, hate having the count in the first element of an array, so I remove it
    _ArrayDelete($aWinList, 0)

    If (UBound($aArray)) Then
        ; First check that the window still exists, if it doesn't then remove it
        For $iProcess = UBound($aArray) - 1 to 0 Step - 1
            If (Not WinExists($aArray[$iProcess][$ARRAY_HANDLE])) Then
                ; Window no longer exists, remove from the array
                _ArrayDelete($aArray, $iProcess)
            EndIf
        Next
    EndIf

    For $iProcess = 0 To UBound($aWinList) -1
        Local $iPid = 0
        Local $iIndex = 0
        
        ; Title of this window is the title we're looking for
        If ($aWinList[$iProcess][$WINLIST_TITLE] = $sWindowTitle) Then
            ; I used PID but you can use the handle, just wanted to throw PID in this script
            $iPid = WinGetProcess($aWinList[$iProcess][$WINLIST_HANDLE])

            If (_ArraySearch($aArray, $iPid, 0, 0, 0, 0, 1, $ARRAY_PID) = -1) Then
                ; Store the current index so we don't have to use UBound 4 times
                $iIndex = UBound($aArray)

                ; Redim the array so we can add the new handle, PID, and count
                ReDim $aArray[$iIndex + 1][UBound($aArray, $UBOUND_COLUMNS)]

                ; Add values
                $aArray[$iIndex][$ARRAY_HANDLE] = $aWinList[$iProcess][$WINLIST_HANDLE]
                $aArray[$iIndex][$ARRAY_PID] = $iPid
                $aArray[$iIndex][$ARRAY_COUNT] = 0
            EndIf
        EndIf
    Next
EndFunc

Give that a go. I cleaned up some of the code, not all. You should rework the state checking to only reset to 0 when the window is visible and active. This can be more easily accomplished using BitAND

If (BitAND($state, 8) and BitAND($state, 2)) Then
    ...
EndIf

It's up to you how you want to determine if a window is inactive though, just my preference.

Thanks so much InunoTaishou - that does exactly what I need it to. I'll have a play with BitAnd, but for the moment I've just added all the various windows states used by my application in the status check.

 

Regards,

Jaycee

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