What to do when "A" getting the current active window misses?

Discuss the future of the AutoHotkey language
iseahound
Posts: 1582
Joined: 13 Aug 2016, 21:04
Contact:

What to do when "A" getting the current active window misses?

13 Jan 2024, 18:41

There's a non-zero chance that any code that uses "A" will bring up a Target not found error. It's not clear to me why it fails, seemingly randomly, but should there be a best practice or some codebase change to mitigate this error?

For example, often simple code like:

Code: Select all

; Closes the window
PostMessage 0x112, 0xF060,,, 'A'  ; 0x112 = WM_SYSCOMMAND, 0xF060 = SC_CLOSE
just fails.

It's not clear to me that each line of code that contains "A" should be systematically wrapped in try {} catch TargetError {return} when there's something wrong with the notion of "A" having a 0.1% chance of failing. As far as the regular user is concerned, there is always an active window. In other words, I don't see why even catching a TargetError could even possibly be a solution to this problem, when the WinTitle could be an ahk_id, throwing a legitimate TargetError. That shouldn't be overlapped with "A" throwing a bs TargetError which has zero meaning to myself or anyone else.
User avatar
andymbody
Posts: 1034
Joined: 02 Jul 2017, 23:47

Re: What to do when "A" getting the current active window misses?

13 Jan 2024, 18:53

I don't know if it is related or not, but I sometimes have an issue when the taskbar receives focus as the active window (briefly). This seems to happen when window focus changes sometimes (like during minimize).
Descolada
Posts: 1458
Joined: 23 Dec 2021, 02:30

Re: What to do when "A" getting the current active window misses?

15 Jan 2024, 15:19

Trouble is, sometimes there isn't an active window, in which case what should be the target? Getting the active window uses GetForegroundWindow which documents that
The foreground window can be NULL in certain circumstances, such as when a window is losing activation.
This means that to guarantee a value for "active window" AHK should substitute it with something the user would expect. Previously it was that the taskbar was returned in such cases, but what if the user wants to wait for the taskbar to be active? If they were to switch windows fast then sometimes the taskbar would be returned, but in actuality it wouldn't be active! Not good. It could be argued that waiting specifically for taskbar focus is a very uncommon goal and thus such a case should be ignored?

Alternatively just check whether an active window exists, just as you would do with any other window:

Code: Select all

if WinExist("A") ; If there is an active window, close it
    PostMessage 0x112, 0xF060 ; 0x112 = WM_SYSCOMMAND, 0xF060 = SC_CLOSE
EDIT: I have no idea where I took that the taskbar was returned, as even in v1 it wasn't. In actuality 0 is returned.
Last edited by Descolada on 20 Apr 2024, 09:45, edited 1 time in total.
User avatar
kczx3
Posts: 1680
Joined: 06 Oct 2015, 21:39

Re: What to do when "A" getting the current active window misses?

16 Jan 2024, 08:23

Wouldn’t there also be a non-zero chance that the active window when WinExist was called is now losing activation when PostMessage is called?

(I’m just playing devils advocate here)
Descolada
Posts: 1458
Joined: 23 Dec 2021, 02:30

Re: What to do when "A" getting the current active window misses?

17 Jan 2024, 00:23

@kczx3 that is true, which is why my example isn't using "A" as WinTitle but instead Last Found Window, which should mean that it is guaranteed that the message is sent to an actual window. Although in a similar fashion we could argue that "what if the window closes in the small time between those calls?", to which I'm not sure what the correct answer is. Wrap everything in try-catch? In actuality I'd probably just ignore that slight possibility and in production code silence the errors with OnError: can't always account for everything.
iseahound
Posts: 1582
Joined: 13 Aug 2016, 21:04
Contact:

Re: What to do when "A" getting the current active window misses?

17 Jan 2024, 17:35

The main problem is that it's a categorization error. It's easy to write logic for when ahk_class notepad isn't found, but it's harder to deal with "A". Especially since it fails very rarely, but still non-zero.

Suggestions
  1. It could just fail silently, but this probably isn't the v2 way of doing things.
  2. It could throw a specific target error, and maybe a directive to silence those errors.
  3. It could just wait for the next active window with a timeout making it more robust
eugenesv
Posts: 182
Joined: 21 Dec 2015, 10:11

Re: What to do when "A" getting the current active window misses?

16 Apr 2024, 05:45

Descolada wrote:
17 Jan 2024, 00:23
@kczx3 that is true, which is why my example isn't using "A" as WinTitle but instead Last Found Window, which should mean that it is guaranteed that the message is sent to an actual window.
Oh, thanks, I think I've had the exact same bug and was wondering why it existed, "but I've just checked that there is an Active window!!!" So it's not just devils advocating :)

Will try to replace it with a last found
eugenesv
Posts: 182
Joined: 21 Dec 2015, 10:11

Re: What to do when "A" getting the current active window misses?

16 Apr 2024, 05:50

iseahound wrote:
17 Jan 2024, 17:35
Suggestions
  1. It could just wait for the next active window with a timeout making it more robust
I think this might be a better default since I think most of the time you don't care about those temporary activation misses and would be fine using whatever activates in the next moment (and only failing if nothing activates). Maybe have an option to disable it or use A0 (nullable A) which is always precise without any waits and without returning taskbars if there is no window, just directly matching the API?
lexikos
Posts: 9780
Joined: 30 Sep 2013, 04:07
Contact:

Re: What to do when "A" getting the current active window misses?

20 Apr 2024, 08:09

Everything you do with window, keyboard or mouse automation is prone to race conditions and conflicts, since forces outside the script, like the user himself, can affect the state of the window. "A" is no different to any other window specification in that respect.

NOTE: "A" intentionally does not match the foreground window if it is hidden and DetectHiddenWindows is off. Before assuming that "A" is unreliable, be absolutely sure you have DetectHiddenWindows on. It is not sensible for PostMessage or any other function which isn't WinWaitActive to wait for a window to become active and visible.

For example, if some other AutoHotkey script is showing a Menu, it probably has its main window active, and that window is probably hidden.
iseahound wrote:It's easy to write logic for when ahk_class notepad isn't found, but it's harder to deal with "A"
I don't agree that it's any different, or difficult. It always depends on which window the author or user intended to interact with. For your example, I imagine the user's intention would be to close the window that he thought was active. If GetForegroundWindow returned NULL because focus is transitioning, whatever window focus is transitioning to is almost definitely not the one the user thought was active. For your example, the only sensible fallback would be to do nothing. That is easily achieved with three letters (and a space): try.

Regardless of what value WinTitle has, it doesn't make sense to design an automatic countermeasure for unexpected failure to find the window as the intention of the code and user cannot be known. There are also very many functions which use WinTitle, and the ideal reaction to failure likely differs between them.

Falling back to the taskbar (or probably any window) would be nonsense. What can you even do to the taskbar, that you would want any functions to operate on it as a fallback? If the effect of the function is really so unimportant that the user is happy with it operating on whatever window, surely the function could just do nothing and the user would be just as happy. Probably happier, because he hasn't just closed an important window that just unexpectedly popped up, or accidentally shut down Windows. (Sending the SCCLOSE command to the taskbar generally shows the Windows Shutdown dialog. If the user happens to be about to press Enter...)

Descolada wrote:which should mean that it is guaranteed that the message is sent to an actual window.
How can it guarantee that, when the last found window might have been destroyed?

Descolada wrote:Previously it was that the taskbar was returned in such cases
Do you mean that GetForegroundWindow returned the taskbar while a transition was occurring? (I'm not saying that it was so, just trying to guess what you mean.) If it was so, it could have been because the taskbar actually was activated during certain transitions. "Previously it was" implies that it doesn't happen anymore; was that on older OS versions?

iseahound wrote:I don't see why even catching a TargetError could even possibly be a solution to this problem, when the WinTitle could be an ahk_id, throwing a legitimate TargetError.
Explain how this makes any sense. If you want to know what window criteria the function failed to resolve to a window, you need only look at the values you gave the function in the first place. The discussion was about functions which are being called to operate on the active window. There is no ambiguity about what a thrown TargetError would mean if PostMessage is the only call within the try-catch.
iseahound
Posts: 1582
Joined: 13 Aug 2016, 21:04
Contact:

Re: What to do when "A" getting the current active window misses?

20 Apr 2024, 08:55

I generally agree with @eugenesv's proposal.

It's a question about classes (or sets or categories). It's clear what ahk_id 4568 means as it targets one window. On the other hand, ahk_exe Notepad refers to a class of windows. Catching a TargetError in the above 2 cases allows the user to write additional code to bring those windows into existence. There isn't any real code to bring a window of type "A" into existence, other than waiting for the user to make changes on screen. In addition, it seems to be a type mismatch 99% of the time as when "A" is not found, I can clearly see the window I intend to target, it just refuses to do so. I think a TargetError window is hidden may be beneficial if you believe that is a common failure mode.
Descolada
Posts: 1458
Joined: 23 Dec 2021, 02:30

Re: What to do when "A" getting the current active window misses?

20 Apr 2024, 10:00

lexikos wrote:
20 Apr 2024, 08:09
How can it guarantee that, when the last found window might have been destroyed?
True, few, if any things related to interacting with external applications can be guaranteed. It is only a subjectively much more smaller probability that it fails, as the timeframe between the two calls is miniscule.

I wonder what the best practices are to avoid these kinds of problems...
Do you mean that GetForegroundWindow returned the taskbar while a transition was occurring? (I'm not saying that it was so, just trying to guess what you mean.) If it was so, it could have been because the taskbar actually was activated during certain transitions. "Previously it was" implies that it doesn't happen anymore; was that on older OS versions?
It appears I have hallucinated this fact, as I couldn't find any proof of it. Most likely I read this line here and for some reason thought that it applies elsewhere, no clue why. I've edited my original post to fix that mistake.
lexikos
Posts: 9780
Joined: 30 Sep 2013, 04:07
Contact:

Re: What to do when "A" getting the current active window misses?

22 Apr 2024, 05:24

iseahound wrote:
20 Apr 2024, 08:55
There isn't any real code to bring a window of type "A" into existence,
There absolutely is. WinActivate. Run. Anything else that activates a window. :roll:
In addition, it seems to be a type mismatch 99% of the time as when "A" is not found, I can clearly see the window I intend to target, it just refuses to do so.
"A" means "the active window", not "the window the user is looking at". Your perception doesn't determine fact. You thought a window was active, and either it became inactivate or you were mistaken. If you were mistaken, there is no way that any of the suggestions so far will help the function find the window that you intended to target. If the window simply became inactive, waiting for the next window to become active will almost certainly not do what you intended, as I already said. It will only make the function operate on a window that you did not intend, instead of halting the script and informing you of the unexpected condition.
I think a TargetError window is hidden may be beneficial if you believe that is a common failure mode.
I think you took too many shortcuts in writing that sentence.
e-t-l
Posts: 5
Joined: 19 Aug 2024, 01:48
Contact:

Re: What to do when "A" getting the current active window misses?

08 Sep 2024, 13:14

I think I encountered this issue, but oddly it was wrapped in an IF clause like in Descolada's first comment.
I am using a script that is intended to detect when all windows are minimized/the desktop is focused (I copied it originally from somewhere on this forum, I think, though I don't remember where).

Code: Select all

{
    if (WinGetTitle("A") = '') {
	WinMinimizeAllUndo
    } else {
	WinMinimizeAll
    }
    Return
}
And I got this runtime "target not found" error. What I don't understand is, since it's an IF clause, shouldn't it just return

Code: Select all

false
?
neogna2
Posts: 619
Joined: 15 Sep 2016, 15:44

Re: What to do when "A" getting the current active window misses?

09 Sep 2024, 11:16

e-t-l wrote:
08 Sep 2024, 13:14
What I don't understand is, since it's an IF clause, shouldn't it just return false?
In order to evaluate the whole if clause the component WinGetTitle("A") must be evaluated and that's what throws the error in the unusual cases discussed in this topic.

Return to “AutoHotkey Development”

Who is online

Users browsing this forum: Bing [Bot] and 3 guests