| View previous topic :: View next topic |
| Author |
Message |
JBensimon
Joined: 16 Nov 2004 Posts: 130 Location: New York
|
Posted: Sun Feb 20, 2005 7:58 pm Post subject: "Keping track" of a window? |
|
|
Hello.
Can anybody suggest a reliable way within the AutoHotkey feature set of referring to a particular window (e.g. for the purpose of WinMinimize or WinClose) when its title and contents are subject to unpredictable change over time? The process to which the window belongs would originally have been launched by the AutoHotkey script itself via Run, so the process ID can be assumed to be available, but I don't see an obvious way to get from a process ID to the window that belongs to the process and from there to the window's current title/contents (which seem to be required by window management functions like WinMinimize). [We can assume that a single window is associated with the process, but a solution that acts upon all the windows belonging to the process would be great too].
Thanks,
Jacques. |
|
| Back to top |
|
 |
corrupt
Joined: 29 Dec 2004 Posts: 2397
|
Posted: Sun Feb 20, 2005 9:23 pm Post subject: |
|
|
| Maybe using WinGet |
|
| Back to top |
|
 |
JBensimon
Joined: 16 Nov 2004 Posts: 130 Location: New York
|
Posted: Sun Feb 20, 2005 10:37 pm Post subject: Window tracking... |
|
|
Thanks for the tip. Until I carefully read about WinGet (as a result of your reply), I hadn't realized that "ahk_id <windowID>" can be used as a reference to a window for purposes of WinMinimize, etc. This of course still leaves the problem of obtaining the window ID(s) belonging to the process of interest, but if I understand your suggestion, I should get a list of all windows on the system using WinGet and then, for each one, call WinGet again to get the name of its owning process and thus discover the window(s) of interest. Is this the most straightforward way to figure out which windows belong to a given process?
Thanks again.
Jacques. |
|
| Back to top |
|
 |
jonny
Joined: 13 Nov 2004 Posts: 3004 Location: Minnesota
|
Posted: Sun Feb 20, 2005 11:45 pm Post subject: |
|
|
| Also, I believe an "ahk_pid" is in the making, which would solve your problem. It would eliminate the need to retrieve the title first when using Win commands. |
|
| Back to top |
|
 |
corrupt
Joined: 29 Dec 2004 Posts: 2397
|
Posted: Sun Feb 20, 2005 11:48 pm Post subject: |
|
|
Here's an example:
| Code: | #Persistent
Run, Notepad
WinWait, Untitled - Notepad,
WinGet, notepad1, ID, Untitled - Notepad
MsgBox, This notepad window's id is: %notepad1%
Return
^J::
WinMinimize, ahk_id %notepad1%
Return
^K::
WinRestore, ahk_id %notepad1%
Return
|
This will run Notepad. Now load a file and note that the window title changes but you will still be able to reference the window by the ahk_id. |
|
| Back to top |
|
 |
JBensimon
Joined: 16 Nov 2004 Posts: 130 Location: New York
|
Posted: Tue Feb 22, 2005 12:54 am Post subject: Thanks again |
|
|
The code I wound up using is similar but not quite identical to what you suggest (and thanks for the effort, by the way). The twist in my requirement is that at no point do I know enough about the launched window to obtain its ID directly via WinGet (because I am basically passed an unknown command line to Run), so what I had to do after launching the command (and capturing the resulting PID) was to enumerate *all* windows via WinGet (List option) and then loop through the resulting array of window IDs to find the one(s) with matching PID (using WinGet to obtaind the PID of each window's owning process and comparing it to my previously saved PID). This lets me identify the window ID(s) of the window(s) belonging to the launched process for use in window management function calls.
Two notes:
(1) The documentation of WinGet does not make it clear that the "ahk_id <windowID>" syntax may be used to obtain information on a window (such as its owning PID). Title/Text and ahk_class are mentioned in the WinGet doc, but not ahk_id (though it works just fine).
(2) Run is very finicky about when it does and doesn't provide a resulting PID. Is Run implemented using ShellExecuteEx, by any chance? I know that this call only returns a PID when an actual new process is launched (which for example isn't the case when a document is launched and opened by an already running process). Strangely, however, I have found that using Run with an explicit fully qualified path to an executable does return a PID, but using Run with just an executable name and relying on its presence in %PATH% (or other form of shell integration) does NOT return a usable PID. Is this normal, or should I report it elsewhere?
Thanks also to "jonny" for mentioning an (upcoming?) ahk_pid feature. Do I understand correctly that this will provide a way of referring to windows by the PID of their owning process? If that's the case, would WinMinimize, ahk_pid %ProcessID% act upon *all* the windows belonging to the specified process? [For that matter, how dows WinMinimize, ahk_class %ClassID% behave now when there are multiple windows of the specified class?]
Man, do I love AutoHotkey!
Jacques. |
|
| Back to top |
|
 |
jonny
Joined: 13 Nov 2004 Posts: 3004 Location: Minnesota
|
Posted: Tue Feb 22, 2005 1:31 am Post subject: |
|
|
*laughs* I love the quotes around my handle.
I believe when multiple windows are found, it acts on the topmost one, but I'm not sure. |
|
| Back to top |
|
 |
Chris Site Admin
Joined: 02 Mar 2004 Posts: 10467
|
Posted: Tue Feb 22, 2005 1:33 am Post subject: Re: Thanks again |
|
|
| JBensimon wrote: | | The documentation of WinGet does not make it clear that the "ahk_id <windowID>" syntax may be used to obtain information on a window (such as its owning PID). | Thanks, that will be clarified.
| Quote: | | Run is very finicky about when it does and doesn't provide a resulting PID. Is Run implemented using ShellExecuteEx, by any chance? | Run and RunWait first attempt CreateProcess() (except for system verbs such as properties). If CreateProcess() fails, ShellExecuteEx() is used.
| Quote: | | I have found that using Run with an explicit fully qualified path to an executable does return a PID, but using Run with just an executable name and relying on its presence in %PATH% (or other form of shell integration) does NOT return a usable PID. | Executables in the PATH should yield a valid PID because CreateProcesss should be able to launch them. Try this example: | Code: | Run, notepad,,, PID
Process, Exist, %PID%
if ErrorLevel = %PID%
MsgBox Yes it exists. | By contrast, ShellExecuteEx() does not (as far as I know) yield a PID. The only way to easily get one from it, that I know of, is to use GetProcessID(), which is only available on Windows XP SP1. Because of this, PID-retrieval is currently not implemented when Run or RunWait falls back to ShellExecuteEx().
| Quote: | | would WinMinimize, ahk_pid %ProcessID% act upon *all* the windows belonging to the specified process? | No, both ahk_class and ahk_pid operate upon the topmost matching window if there is more than one match. You could use WinGet to retrieve a list of all windows belonging to a certain class or PID. |
|
| Back to top |
|
 |
JBensimon
Joined: 16 Nov 2004 Posts: 130 Location: New York
|
Posted: Tue Feb 22, 2005 2:39 am Post subject: Run and PID |
|
|
Chris,
Thanks for the (as always thorough) reply. I will test the full path / no path Run behavior again and report back if the PID results differ from what you describe.
Pretty amazing that a function to get a process ID from a handle to the process, which ShellExecuteEx does (sometimes!) return, has only recenly been added to the API. You'd think that would have been a natural from the word go.
Jacques.
PS: Love the new OutputDebug feature! Maybe you could provide a new directive to turn debugger output on/off (i.e. execute/ignore OutputDebug commands). |
|
| Back to top |
|
 |
JBensimon
Joined: 16 Nov 2004 Posts: 130 Location: New York
|
Posted: Tue Feb 22, 2005 3:12 am Post subject: Run / PATH / PID |
|
|
Chris,
You are quite right that executables in the system %PATH% are launchable via CreateProcess() and therefore do return a PID. The executables I had previously tested (like IExplore.exe and Excel.exe) are listed under the "App Paths" registry key and are therefore launchable (without being fully qualified) by the shell and via ShellExecute(), but not by CreateProcess(), so it stands to reason I was not getting a PIDback from the Run command.
Thanks again.
Jacques. |
|
| Back to top |
|
 |
Chris Site Admin
Joined: 02 Mar 2004 Posts: 10467
|
Posted: Tue Feb 22, 2005 3:23 am Post subject: Re: Run and PID |
|
|
Thanks for the follow-up.
| JBensimon wrote: | | Pretty amazing that a function to get a process ID from a handle to the process, which ShellExecuteEx does (sometimes!) return, has only recenly been added to the API. | I was surprised about that too.
| Quote: | | Maybe you could provide a new directive to turn debugger output on/off (i.e. execute/ignore OutputDebug commands). | It was my understanding that you could simply quit the debugger and the OutputDebug command would have no effect (nor would it consume any memory to save the output somewhere). Also, perhaps debuggers have a way to pause or disable their reception of output temporarily. |
|
| Back to top |
|
 |
JBensimon
Joined: 16 Nov 2004 Posts: 130 Location: New York
|
Posted: Tue Feb 22, 2005 4:03 am Post subject: |
|
|
| Quote: | | It was my understanding that you could simply quit the debugger and the OutputDebug command would have no effect ... |
True enough, the OutputDebugString() API actually does nothing in the absence of a debugger ("If a tree falls in the forest and there's nobody around to hear it, ..." ), but I probably wouldn't want somebody executing my script with DebugView running to see "private" debugging output, so being able to globally turn off OutputDebug could be useful ... but hey, I'm more than willing to do a global replace of "OutputDebug" with "; OutputDebug" before compiling my scripts!
Jacques. |
|
| Back to top |
|
 |
jonny
Joined: 13 Nov 2004 Posts: 3004 Location: Minnesota
|
Posted: Tue Feb 22, 2005 4:03 am Post subject: |
|
|
With DebugView you can filter the incoming messages, too, so there's no need to even quit it. And if you're worried about the performance drop, well then: 1) It's extremely small, hardly worth thinking about from any perspective. 2) Why would you be using a scripting language if you're so worried about infinitesimal performance drops?
Anyway... ya.  |
|
| Back to top |
|
 |
Chris Site Admin
Joined: 02 Mar 2004 Posts: 10467
|
Posted: Tue Feb 22, 2005 10:28 am Post subject: |
|
|
| JBensimon wrote: | | I probably wouldn't want somebody executing my script with DebugView running to see "private" debugging output, so being able to globally turn off OutputDebug could be useful | You could also do the following in each place: | Code: | if not A_IsCompiled
OutputDebug, ... | This requires v1.0.27+. |
|
| Back to top |
|
 |
|