Threads halting unknown reason

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
User avatar
KuroiLight
Posts: 327
Joined: 12 Apr 2015, 20:24
Contact:

Threads halting unknown reason

18 Nov 2017, 16:51

I have the following code, which is supposed to monitor for the lockscreen, unfortunately is halts after the first while loop iteration, any ideas?

Code: Select all

#SingleInstance, force
#Persistent
#MaxThreads, 99

SL := new ScreenLock()

hFile := FileOpen("./sl.log", "w-rwd")

hFile.WriteLine("--!SL.IsScreenLocked()--")
while(!SL.IsScreenLocked()) {
    hFile.WriteLine("SL.LockApp=" . SL.LockApp . " SL.LogonUI=" . SL.LogonUI . " SL.LockAppHost=" . SL.LockAppHost)
    Sleep, 1000
}

hFile.WriteLine("--SL.IsScreenLocked()--")
while(SL.IsScreenLocked()) {
    hFile.WriteLine("SL.LockApp=" . SL.LockApp . " SL.LogonUI=" . SL.LogonUI . " SL.LockAppHost=" . SL.LockAppHost)
    Sleep, 1000
}

hFile.Close()

return

Class ScreenLock {
    __New() {
        LogonUI_Func := this.LogonUI_Func := ObjBindMethod(this, "ProcessStatusUpdate", "LogonUI")
        LockAppHost_Func := this.LockAppHost_Func := ObjBindMethod(this, "ProcessStatusUpdate", "LockAppHost")
        LockApp_Func := this.LockApp_Func := ObjBindMethod(this, "ProcessStatusUpdate", "LockApp")

        this.LockApp := false
        this.LogonUI := false
        this.LockAppHost := false

        SetTimer, %LogonUI_Func%, -1
        SetTimer, %LockAppHost_Func%, -1
        SetTimer, %LockApp_Func%, -1
    }

    LockWorkStation() {
        DllCall("User32\LockWorkStation")
    }

    IsScreenLocked() {
        return (this.LockApp and this.LogonUI and this.LockAppHost)
    }

    ProcessStatusUpdate(exename) {
        this[exename] := false
        Loop {
            Process, Wait, % exename . ".exe"
            this[exename] := (ErrorLevel ? true : false)
            Process, WaitClose, % exename . ".exe"
            this[exename] := (ErrorLevel ? true : false)
            Sleep, 25
        }
    }
}
Last edited by KuroiLight on 18 Nov 2017, 21:37, edited 1 time in total.
Windows 10, Ryzen 1600, 16GB G.Skill DDR4, 8GB RX 480 | [MyScripts][MySublimeSettings] [Unlicense][MIT License]
01/24/18
[/color]
A_AhkUser
Posts: 1147
Joined: 06 Mar 2017, 16:18
Location: France
Contact:

Re: Threads halting unknown reason

18 Nov 2017, 21:25

Not sure but I think IsScreenLocked always returns true:

Code: Select all

MsgBox % (0 == 1 == 0 == true) ; always true
MsgBox % (0 and 1 and 0 and true)
MsgBox % (1 and 1 and 1 and true)
MsgBox % (0 == true)
my scripts
User avatar
KuroiLight
Posts: 327
Joined: 12 Apr 2015, 20:24
Contact:

Re: Threads halting unknown reason

18 Nov 2017, 21:38

A_AhkUser wrote:Not sure but I think IsScreenLocked always returns true:

Code: Select all

MsgBox % (0 == 1 == 0 == true) ; always true
MsgBox % (0 and 1 and 0 and true)
MsgBox % (1 and 1 and 1 and true)
MsgBox % (0 == true)
strange, fixed that. unfortunately that doesn't fix the halting problem... :headwall:

edit* just realized why (0 == 1 == 0 == true) is true, derp...
Last edited by KuroiLight on 18 Nov 2017, 21:53, edited 1 time in total.
Windows 10, Ryzen 1600, 16GB G.Skill DDR4, 8GB RX 480 | [MyScripts][MySublimeSettings] [Unlicense][MIT License]
01/24/18
[/color]
User avatar
Spawnova
Posts: 555
Joined: 08 Jul 2015, 00:12
Contact:

Re: Threads halting unknown reason

18 Nov 2017, 21:51

I believe your problem lies here

Code: Select all

ProcessStatusUpdate(exename) {
        this[exename] := false
        Loop { ;<<<-----------------------------------------------This loop never breaks and takes priority of the rest of the script
            Process, Wait, % exename . ".exe"
            this[exename] := (ErrorLevel ? true : false)
            Process, WaitClose, % exename . ".exe"
            this[exename] := (ErrorLevel ? true : false)
            Sleep, 25
        }
    }
as you can see in this example code

Code: Select all

func := new a()

while(1) {
	tooltip in the while loop
	sleep 100
}
return

f8::exitapp

class a {
	__New() {
		func := this.func := ObjBindMethod(this, "_func", "func")
		settimer,%func%,-1
	}
	
	_func() {
		loop {
			sleep 1000
			tooltip currently in class loop
		}
	}
}
it gets stuck in the class loop

I'm not sure if you can have both loops going at the same time
User avatar
KuroiLight
Posts: 327
Joined: 12 Apr 2015, 20:24
Contact:

Re: Threads halting unknown reason

18 Nov 2017, 21:58

What I take from Threads and Thread is that multiple timers can run "at the same time" context switching between the them periodically, I assume it doesn't matter what those thread are running for the most part.
Might be that either this is an not correct and the docs simply don't mention it or this is a bug in ahk? not sure
Windows 10, Ryzen 1600, 16GB G.Skill DDR4, 8GB RX 480 | [MyScripts][MySublimeSettings] [Unlicense][MIT License]
01/24/18
[/color]
User avatar
KuroiLight
Posts: 327
Joined: 12 Apr 2015, 20:24
Contact:

Re: Threads halting unknown reason

18 Nov 2017, 22:06

I would assume that once the code gets to Process, Wait ...., it waits the default 15ms [specified under Thread, Interrupt,,] and switches back to the main thread or other timer threads. Am I wrong here?
Windows 10, Ryzen 1600, 16GB G.Skill DDR4, 8GB RX 480 | [MyScripts][MySublimeSettings] [Unlicense][MIT License]
01/24/18
[/color]
User avatar
joedf
Posts: 8958
Joined: 29 Sep 2013, 17:08
Location: Canada
Contact:

Re: Threads halting unknown reason

22 Nov 2017, 20:03

I think you might want to avoid a class for something like this... there isn’t much benefit, and you can lock only one workstation ...
Might be easier to debug without... something feels off about those settimers...
Image Image Image Image Image
Windows 10 x64 Professional, Intel i5-8500, NVIDIA GTX 1060 6GB, 2x16GB Kingston FURY Beast - DDR4 3200 MHz | [About Me] | [About the AHK Foundation] | [Courses on AutoHotkey]
[ASPDM - StdLib Distribution] | [Qonsole - Quake-like console emulator] | [LibCon - Autohotkey Console Library]
User avatar
KuroiLight
Posts: 327
Joined: 12 Apr 2015, 20:24
Contact:

Re: Threads halting unknown reason

23 Nov 2017, 19:18

I agree that this normally wouldn't be the type of thing to put in a class, but its actually supposed to go into a larger class and work with other code.
anyways this doesn't seem to work either:

Code: Select all

global processes := {}

LogonUI_Func := Func("ProcessStatusUpdate").Bind("LogonUI")
LockAppHost_Func := Func("ProcessStatusUpdate").Bind("LockAppHost")
LockApp_Func := Func("ProcessStatusUpdate").Bind("LockApp")

SetTimer, %LogonUI_Func%, -1
SetTimer, %LockAppHost_Func%, -1
SetTimer, %LockApp_Func%, -1

While(!IsScreenLocked())
    Sleep, 1000

MsgBox, % "Screen Got Locked"
ExitApp, 0
return

ProcessStatusUpdate(exename) {
    processes[exename] := false

    Loop {
        Process, Wait, % exename . ".exe"
        processes[exename] := (ErrorLevel ? true : false)
        Process, WaitClose, % exename . ".exe"
        processes[exename] := (ErrorLevel ? true : false)
        Sleep, 25
    }
}

IsScreenLocked() {
    return (processes["LogonUI"] and processes["LockAppHost"] and processes["LockApp"])
}
Windows 10, Ryzen 1600, 16GB G.Skill DDR4, 8GB RX 480 | [MyScripts][MySublimeSettings] [Unlicense][MIT License]
01/24/18
[/color]
User avatar
KuroiLight
Posts: 327
Joined: 12 Apr 2015, 20:24
Contact:

Re: Threads halting unknown reason

23 Nov 2017, 19:36

ok so I added some logging code into the script and tested heres what I get:
Script with logging

Code: Select all

global processes := {}
global dbgLogger := new LogFile(,false,,"mm.ss")

LogonUI_Func := Func("ProcessStatusUpdate").Bind("LogonUI")
LockAppHost_Func := Func("ProcessStatusUpdate").Bind("LockAppHost")
LockApp_Func := Func("ProcessStatusUpdate").Bind("LockApp")

SetTimer, %LogonUI_Func%, -1
SetTimer, %LockAppHost_Func%, -1
SetTimer, %LockApp_Func%, -1

While(!IsScreenLocked()) {
    Sleep, 2000
}

MsgBox, % "Screen Got Locked"
ExitApp, 0
return

ProcessStatusUpdate(exename) {
    dbgLogger.AddEntry(A_TickCount . ": " . "timer initiate function for " . exename)
    processes[exename] := false

    Loop {
        Process, Wait, % exename . ".exe"
        processes[exename] := (ErrorLevel ? true : false)
        dbgLogger.AddEntry(A_TickCount . ": " . exename . " was found=" . processes[exename])
        Process, WaitClose, % exename . ".exe"
        processes[exename] := (ErrorLevel ? true : false)
        dbgLogger.AddEntry(A_TickCount . ": " . exename . " was found=" . processes[exename])
        Sleep, 25
    }
}

IsScreenLocked() {
    dbgLogger.AddEntry(A_TickCount . ": " . "Screen lock check: LogonUI=" . processes["LogonUI"] . ", LockAppHost=" . processes["LockAppHost"] . ", LockApp=" . processes["LockApp"])
    return (processes["LogonUI"] and processes["LockAppHost"] and processes["LockApp"])
}







;;-----------------------------
Class LogFile {
    __New(filename := "", insertAtTop := true, maxEntries := 150, dt_format := "-1") {
        A_ScriptNameNoExt := RegExReplace(A_ScriptName, "iDU)^(.*)\.(ahk|exe)$", "$1") ;not usually here
        this.timestamp_enabled := (dt_format != "-1" ? true : false)
        this.timestamp_format := dt_format
        this.filename := AbsolutePath(filename ? filename : A_ScriptDir . "\" . A_ScriptNameNoExt . ".log")
        this.max := maxEntries
        this.insertAtTop := insertAtTop
        this.Slurp()
        this.Prune()
        this.UpdateFile()
    }

    AddEntry(message) {
        message := "[" . A_ScriptNameNoExt . "]" . message
        if(this.timestamp_enabled)
            message := RTrim("[" . FormatTime(A_Now, this.timestamp_format) . "] " . message, "`r`n")
        split_msg := StrSplit(message, "`n")
        Loop % split_msg.Length() {
            if(this.insertAtTop) {
                this.contents.InsertAt(A_Index, split_msg[A_Index])
            } else {
                this.contents.Push(message)
            }
        }
        this.Prune()
        this.UpdateFile()
    }

    UpdateFile() {
        hFile := FileOpen(this.filename, "w-rwd")
        for i, v in this.contents {
            hFile.WriteLine(v)
        }
        hFile.Close()
    }

    Prune() {
        While(this.max < this.contents.Length()) {
            if(this.insertAtTop)
                this.contents.Pop()
            else
                this.contents.RemoveAt(1)
        }
    }

    Slurp() {
        this.contents := Array()
        Loop, Read, % this.filename
        {
            this.contents.Push(A_LoopReadLine)
        }
    }

    __Delete() {
        this.timestamp_enabled := ""
        this.timestamp_format := ""
        this.filename := ""
        this.max := ""
        this.insertAtTop := ""
        While(this.contents.Length() > 0)
            this.contents.Pop()
    }
}

AbsolutePath(filename) {
    if(filename ~= "S)^\..+$") {
        filename := A_WorkingDir . SubStr(filename, 2)
    }
    Loop {
        filename := RegExReplace(filename, "S)^(.+\\)?.+[^\.]{2}\.\.[\\]?(.+)?$", "$1$2", replaces)
    } Until !replaces
    return filename
}

FormatTime(YYYYMMDDHHMISS := "", Format := "") {
    FormatTime, output_var, %YYYYMMDDHHMISS%, %Format%
    return output_var
}
Logfile

Code: Select all

[44.45] []3742578: Screen lock check: LogonUI=, LockAppHost=, LockApp=
[44.46] []3742687: timer initiate function for LogonUI
[44.46] []3742796: timer initiate function for LockApp
[44.58] []3755500: LockApp was found=1
[45.11] []3768125: LockApp was found=0
;restarted script
[01.12] []4728656: Screen lock check: LogonUI=, LockAppHost=, LockApp=
[01.12] []4728765: timer initiate function for LogonUI
[01.12] []4728781: timer initiate function for LockAppHost
[01.12] []4728796: timer initiate function for LockApp
[01.35] []4752375: LockApp was found=1
[01.55] []4772250: LockApp was found=0
I ran the script, waited a few seconds, locked the screen, waited a few seconds, unlocked waited. I ran it twice to be sure.
Seems SetTimer is successful [sometimes] but process, wait never gets executed for any but the last SetTimer and the While(!IsScreenLocked()) { loop only iterates once...
The log also shows that ProcessStatusUpdate function works [atleast for LockApp] but just isn't being run from the other timers. I guess something like GreenThreads would come in handing for these sort of things instead of using Timers in an unintended way.;
still no idea why this is happening...
Windows 10, Ryzen 1600, 16GB G.Skill DDR4, 8GB RX 480 | [MyScripts][MySublimeSettings] [Unlicense][MIT License]
01/24/18
[/color]
User avatar
KuroiLight
Posts: 327
Joined: 12 Apr 2015, 20:24
Contact:

Re: Threads halting unknown reason

23 Nov 2017, 21:03

On a side note: Is there any reason why Process, Exist would be able to see a process and WinExist wouldn't? even with DetectHiddenWindows, On.
Windows 10, Ryzen 1600, 16GB G.Skill DDR4, 8GB RX 480 | [MyScripts][MySublimeSettings] [Unlicense][MIT License]
01/24/18
[/color]
User avatar
KuroiLight
Posts: 327
Joined: 12 Apr 2015, 20:24
Contact:

Re: Threads halting unknown reason

23 Nov 2017, 21:49

Well I went another route for this specific task which seems to have achieved my goal:

Code: Select all

global WM_WTSSESSION_CHANGE := 0x2b1, WTS_SESSION_LOCK := 0x7, WTS_SESSION_UNLOCK := 0x8, ScreenLocked := false
thisPid := DllCall("GetCurrentProcessId")
thisHwnd := WinExist("ahk_pid " . thisPid)
DllCall("Wtsapi32\WTSRegisterSessionNotification", UInt, thisHwnd, Int, 1, Int)

OnMessage(WM_WTSSESSION_CHANGE, "SessionChangeEvent")

return

SessionChangeEvent(wParam, lParam, msg, hwnd) {
    if(wParam == WTS_SESSION_LOCK)
        ScreenLocked := true
    else if(wParam == WTS_SESSION_UNLOCK)
        ScreenLocked := false
}
don't know why I didn't take this route before...

would still like to know whats going on with the Timers though.
Windows 10, Ryzen 1600, 16GB G.Skill DDR4, 8GB RX 480 | [MyScripts][MySublimeSettings] [Unlicense][MIT License]
01/24/18
[/color]
User avatar
joedf
Posts: 8958
Joined: 29 Sep 2013, 17:08
Location: Canada
Contact:

Re: Threads halting unknown reason

23 Nov 2017, 23:39

In my experience, the Process, * functions are not very reliable... :/
KuroiLight wrote:On a side note: Is there any reason why Process, Exist would be able to see a process and WinExist wouldn't? even with DetectHiddenWindows, On.
If they are purely console (subsystem flagged) applications, some of them never create any windows whatsoever, not even hidden ones...

...anyway, Great use of Dllcall, generally more reliable for system things like this... :+1:
Image Image Image Image Image
Windows 10 x64 Professional, Intel i5-8500, NVIDIA GTX 1060 6GB, 2x16GB Kingston FURY Beast - DDR4 3200 MHz | [About Me] | [About the AHK Foundation] | [Courses on AutoHotkey]
[ASPDM - StdLib Distribution] | [Qonsole - Quake-like console emulator] | [LibCon - Autohotkey Console Library]

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: Google [Bot], inseption86, jaka1, mebelantikjaya and 306 guests