Add a command to turn off TargetError() Topic is solved

Discuss the future of the AutoHotkey language
crocodile
Posts: 98
Joined: 28 Dec 2020, 13:41

Add a command to turn off TargetError()

Post by crocodile » 19 Jun 2022, 09:50

The window command is the one we use the most, but when I started using V2-beta I had to use a lot of "try" commands to block the unlimited TargetError(). Yes, I can modify my script so that it no longer reports errors. But I wonder if people who don't need this command, who are never interested in the information it provides, and who are just unhappy with it, can use the window command as easily as V1?
I think for many people, V1's window command has no drawbacks. And TargetError() seems like V2 is selling its rigour by telling you that I am that rigorous and you must accept it. Whether this is necessary or not.

This is a most typical V2 window command.

Code: Select all

	control:=""
	try control:=ControlGetHwnd("SysTreeView321", "ahk_class CabinetWClass")
	if control
	{
		hwnd:=DllCall("GetAncestor", "Ptr", control, "Uint", 2)
		WinActivate(hwnd)
	} Else
	{
		run("explorer.exe")
	}
And this is a V1

Code: Select all

	if control:=ControlGetHwnd("SysTreeView321", "ahk_class CabinetWClass")
	{
		hwnd:=DllCall("GetAncestor", "Ptr", control, "Uint", 2)
		WinActivate(hwnd)
	} Else
	{
		run("explorer.exe")
	}

Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: Add a command to turn off TargetError()

Post by Helgef » 19 Jun 2022, 12:07

in v2, I'd do like this,

Code: Select all

try 
{
	control:=ControlGetHwnd("SysTreeView321", "ahk_class CabinetWClass")
	hwnd:=DllCall("GetAncestor", "Ptr", control, "Uint", 2, 'ptr') ; use 'ptr' for the return value.
	WinActivate(hwnd)
} catch TargetError
{
	run("explorer.exe")
}
Which is more robust than the v1 code, as it will run explorer.exe if any of the window functions fails to identify its target. It is better now.

Cheers.

crocodile
Posts: 98
Joined: 28 Dec 2020, 13:41

Re: Add a command to turn off TargetError()

Post by crocodile » 19 Jun 2022, 20:23

@Helgef

In fact the example you modified is not appropriate. Especially when you need to intersperse other commands with window commands, errors in other commands will trigger 'run("explorer.exe")'. This is an error I've already encountered.

Code: Select all

try 
{
	control:=ControlGetHwnd("SysTreeView321", "ahk_class CabinetWClass")
	hwnd:=DllCall("GetdAncestor2", "Ptr", control, "Uint", "a", 'ptr') ; use 'ptr' for the return value.
	WinActivate(hwnd)
} catch TargetError
{
	run("explorer.exe")
}


I know there are really a lot of people who need TargetError, but there are also a lot of people who don't need it. Why not provide a switch? Wouldn't it be nice to let people who need it turn it on, and let people who don't need it block it, and nobody has anything to lose?

crocodile
Posts: 98
Joined: 28 Dec 2020, 13:41

Re: Add a command to turn off TargetError()

Post by crocodile » 19 Jun 2022, 21:00

In fact, we had to use a lot of "try" in V2, which made the code very ugly. I think what we really need to avoid is not TargetError, but rather to avoid using "try".
On the contrary, we have to use the even less strict "try" to avoid the nuisance of TargetError

Code: Select all

isfunc(fn) -> try type(%fn%)="func"
if WinExist("A") -> try if WinExist("A")

Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: Add a command to turn off TargetError()

Post by Helgef » 20 Jun 2022, 02:31

It is appropriate for the example, you want to trigger run if you cannot activate a specific window, i.e, if either controlgethwnd or winactivate throws a targeterror. dllcall will not throw a targeterror, but will kindly, unlike v1, inform you if you make mistakes such as in your example. And I think It goes without saying that if you add functions to the block for which a thrown targeterror shouldn't result in run, you'll need to handle it.

I'm not sure I follow you last post, but note, winexist will not throw a targeterror.

Cheers.

lexikos
Posts: 9583
Joined: 30 Sep 2013, 04:07
Contact:

Re: Add a command to turn off TargetError()

Post by lexikos » 20 Jun 2022, 06:14

You want all windowing commands to continue as if they succeeded, even when the window has been closed, or the title is wrong? If the script doesn't depend on those commands succeeding, why use them in the first place?

If you're retrieving information from a window or control, you want it to tell you the answer is "" when you make a typo in the title?

It can already be achieved with OnError (for any continuable error), but I wouldn't recommend it.

There's rarely a good reason to reference functions by strings - use references instead. If you've found what you think is a good reason, it's still not a good example of try being inconvenient. All you need is a single function definition, then you can avoid repeating not only the try but also the type check. I'd also add that Type() is nearly never the right choice for checking the type of a value; you should use x is Func in this case, or for more flexibility, HasMethod(x) ('Call' is implied).

Another point against IsFunc is that after you know it's a valid function name, you almost always need to resolve it back to a function. By trying to use a direct equivalent of v1's IsFunc, you are writing unnecessarily inefficient code.
To validate, you need to perform the double-deref first (b := %a%). Once you've done that, there probably isn't a good reason to do it again; instead, keep the value and call it like any other callable value (b()).
Source: Preview of changes: scope, function and variable references - AutoHotkey Community

crocodile
Posts: 98
Joined: 28 Dec 2020, 13:41

Re: Add a command to turn off TargetError()

Post by crocodile » 21 Jun 2022, 09:06

@lexikos Thank you.

But the fact remains that we still need to use "try" a lot.
The "try" is a bigger hazard than the "window exists or not".

I was wondering if you use the window command a lot?

------


Yes, I only need wingettitle() to return "" or the title.
In 99% of cases, I don't need to care if the window exists, I just need to know if I'm getting a title with content.
Maybe 1% of the time I need to know if the window is there or not, then I will use WinExist()
Is this use not allowed?
Or would this be seen as blasphemy against the rigour of V2?


It's hard to imagine that I now mainly use my own wrapped WIN commands. I'm afraid to use the built-in command, I'm afraid of its pop-ups, to me it's as pointless as an advertisement.

Code: Select all

win_gettitle(hwnd) {
	static buf := buffer(512, 0)
	if sz := DllCall("GetWindowTextW", "Ptr", hwnd, "Ptr", buf.ptr, "uint", 512)
		return StrGet(buf.ptr, sz, "utf-16")
}
Perhaps because of my poor programming skills, when I look at my modified V2 code, I find it very ugly.

Code: Select all

	aid := WinExist("A"), id:=""
	try
		name:=WinGetProcessName(aid)
	catch
		name:=""

	if InStr("\Chrome.exe\Opera.exe\firefox.exe\vivaldi.exe\msedge.exe\", "\" name "\")
		id := aid
	else
	{

		mode := A_TitleMatchMode
		SetTitleMatchMode "RegEx"
		try id := WinGetID("ahk_exe i)\\(chrome.exe|opera.exe|firefox.exe|vivaldi.exe|msedge.exe)$")
		SetTitleMatchMode mode
	}

	if id
	{
		try path := wingetProcessPath(id)
		try pid := WinGetpid(id)
	}

Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: Add a command to turn off TargetError()

Post by Helgef » 21 Jun 2022, 13:06

It's hard to imagine that I now mainly use my own wrapped WIN commands.
Instead if reimplementing the built in functions to avoid targeterror, just wrap the built in functions or perhaps even better,

Code: Select all

class _try {
	static __call(fn, p) {
		try return %fn%(p*)
		catch targeterror
			return 
	}
}
Just call _try.wingettitle() or any other function.
Perhaps because of my poor programming skills, when I look at my modified V2 code, I find it very ugly.
Ugly or not is subjective, but v2 code will be more robust than v1 code, in general.

Cheers.

lexikos
Posts: 9583
Joined: 30 Sep 2013, 04:07
Contact:

Re: Add a command to turn off TargetError()  Topic is solved

Post by lexikos » 21 Jun 2022, 17:23

crocodile wrote:
21 Jun 2022, 09:06
The "try" is a bigger hazard than the "window exists or not".
I don't agree.

Regardless of any arguments for or against,
  • It won't be changed, and is now a matter of backward-compatibility.
  • You can already disable it, as I said.

crocodile
Posts: 98
Joined: 28 Dec 2020, 13:41

Re: Add a command to turn off TargetError()

Post by crocodile » 21 Jun 2022, 20:20

@Helgef
@lexikos

OK, thanks.
Although I was expecting OnTargetError(), at least there is an "OnError((*) => -1)" as a consolation.

Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: Add a command to turn off TargetError()

Post by Helgef » 22 Jun 2022, 02:28

at least there is an "OnError((*) => -1)" as a consolation.
That is a poor solution, at the very least you should filter for targeterrors, eg,

Code: Select all

onerror (e,*) => -(e is targeterror)
Cheers.

Edit, :arrow: example where v2 targeterror would have saved the day ;)

Post Reply

Return to “AutoHotkey Development”