Detecting multiple instances when using WinWait or WinActivate

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
eagerahk
Posts: 122
Joined: 02 Dec 2015, 06:27

Detecting multiple instances when using WinWait or WinActivate

02 Aug 2021, 23:55

How can we detecting multiple instances of any application when using WinWait or WinActivate?
The following code does not work for the second instance.

Code: Select all

Run, Notepad
WinWait, ahk_class Notepad 
Run, Notepad
WinWait, ahk_class Notepad 
If somehow there is no way to detect multiple instances, may be I can copy Notepad.exe to Notepad1.exe, Notepad2.exe, Notepad3.exe, ..etc.

Code: Select all

Run, Notepad
WinWait, ahk_exe Notepad.exe 
Run, Notepad1.exe
WinWait, ahk_exe Notepad1.exe 
Run, Notepad2.exe
WinWait, ahk_exe Notepad2.exe 
Run, Notepad3.exe
WinWait, ahk_exe Notepad3.exe 
But, this does not sound too good.

Thanks a lot!
Rohwedder
Posts: 7550
Joined: 04 Jun 2014, 08:33
Location: Germany

Re: Detecting multiple instances when using WinWait or WinActivate

03 Aug 2021, 04:04

Hallo,
try:

Code: Select all

Loop, 4
{
	Run, Notepad,,, PID
	WinWait, ahk_pid %PID%
}
If you want to activate them individually:

Code: Select all

Loop, 4
{
	Run, Notepad,,, PID%A_Index%
	WinWait,% "ahk_pid " PID%A_Index%
}
Return
1::
2::
3::
4::WinActivate,% "ahk_pid " PID%A_ThisHotkey%
eagerahk
Posts: 122
Joined: 02 Dec 2015, 06:27

Re: Detecting multiple instances when using WinWait or WinActivate

03 Aug 2021, 19:33

Thank you for reminding me of PID.
I tried the following code, but could not make it work:

Code: Select all

#SingleInstance, force
run "C:\Program Files (x86)\Microsoft Office\Office12\WINWORD.EXE",,,pid1
WinWait, ahk_pid %pid1%
run "C:\Program Files (x86)\Microsoft Office\Office12\WINWORD.EXE",,,pid2
WinWait, ahk_pid %pid2%           ; for unknown reason, the process stops here forever
sleep 100

WinActivate, ahk_pid %pid1%
sleep 300
send This is the first instance of Word 2007, to be placed to the left side
sleep 100
send #{Left}
sleep 100

WinActivate, ahk_pid %pid2%
sleep 300
send This is the second instance of Word 2007, to be placed to the right side
sleep 100
send #{Right}
sleep 100

msgbox "Hello--" %pid1% " , " %pid2%
ExitApp
Thanks!
User avatar
boiler
Posts: 16767
Joined: 21 Dec 2014, 02:44

Re: Detecting multiple instances when using WinWait or WinActivate

03 Aug 2021, 19:52

I don't know about your version of Word, but mine won't open the second instance until I choose a file (or new blank document) from the first one. But even after that, the window of the new instance is still opened under the first PID, unlike the Notepad windows that each had their own. You can use the Window Spy tool to see that they were both show the same PID, despite the Run command showing a different PID for running the second one. It turns out to be the same PID as the first one after it's actually opened.
Rohwedder
Posts: 7550
Joined: 04 Jun 2014, 08:33
Location: Germany

Re: Detecting multiple instances when using WinWait or WinActivate

04 Aug 2021, 00:37

This works here with Word 2019:

Code: Select all

#SingleInstance, force
run "WINWORD.EXE" /t,,,pid1
WinWait, ahk_pid %pid1%
Sleep, 2000
run "WINWORD.EXE" /t,,,pid2
WinWait, ahk_pid %pid2%
Sleep, 2000
WinActivate, ahk_pid %pid1%
sleep 300
SendInput This is the first instance of Word 2007, to be placed to the left side
sleep 1000
send #{Left}
sleep 100
WinActivate, ahk_pid %pid2%
sleep 300
SendInput This is the second instance of Word 2007, to be placed to the right side
sleep 1000
send #{Right}
sleep 100

msgbox "Hello--" %pid1% " , " %pid2%
ExitApp
eagerahk
Posts: 122
Joined: 02 Dec 2015, 06:27

Re: Detecting multiple instances when using WinWait or WinActivate

04 Aug 2021, 02:48

Thank you very much. Rohwedder.

I used your code and it works for Word 2007 here as well. Examining your code and mine, there are two important differences:

1. Run .... /t,,,pid1 ←←my code did not have /t

2. your code has Sleep, 2000 after WinWait, this is very critical. Without it the whole thing won't work as planned. But this puzzled me because shouldn't WinWait suppose to take care of all the necessary wait without us to issue an additional Sleep, xxxx? If WinWait can not guarantee it will wait enough time so that we need to issue our own Sleep, xxxx, that raises two problems:
  • A. How much waiting time is needed? Sleep, 2000 or Sleep, 5000? In a test, we may find
    that 2000 is fine, but if we are running other applications concurrently and the system resource is
    strained, 2000 may not be enough. Therefore, WinWait does not take care of this is a concern.
  • B. If WinWait really can not guarantee the waiting time is enough, then can we just forget the
    two commands,

    Code: Select all

               WinWait, ahk_pid %pid1%
               Sleep, 2000
    and replace them by one command Sleep, 9000, or Sleep, 15000?
Thanks a lot!!!
eagerahk
Posts: 122
Joined: 02 Dec 2015, 06:27

Re: Detecting multiple instances when using WinWait or WinActivate

05 Aug 2021, 01:27

In the following code, sample1 and sample2 are any free sample animated GIFs. If we do not comment out WinWaits, we shall never see the window of Hello, World. Do I misunderstand anything here for the purpose of WinWait? Thanks!!

Code: Select all

run "iexplore" "d:\sample1.gif",,,pid1
WinWait, ahk_pid %pid1%
Sleep, 1000
run "iexplore" "d:\sample2.gif",,,pid2
WinWait, ahk_pid %pid2%
Sleep, 1000
msgbox Hello, World
exitapp
Rohwedder
Posts: 7550
Joined: 04 Jun 2014, 08:33
Location: Germany

Re: Detecting multiple instances when using WinWait or WinActivate

05 Aug 2021, 01:33

I just tried with my Word 2019 to reduce the fixed sleeps. This works here:

Code: Select all

run "WINWORD.EXE" /t,,,pid1
WinWait, ahk_pid %pid1%
Sleep, 300
WinActivate, ahk_pid %pid1%
WinWaitActive, ahk_pid %pid1%
Loop
{
	ControlGetFocus, ClassNN
	Sleep, 100
}
Until, ClassNN = _WwG1
run "WINWORD.EXE" /t,,,pid2
WinWait, ahk_pid %pid2%
Sleep, 300
WinActivate, ahk_pid %pid2%
WinWaitActive, ahk_pid %pid2%
Loop
{
	ControlGetFocus, ClassNN
	Sleep, 100
}
Until, ClassNN = _WwG1
WinActivate, ahk_pid %pid1%
WinWaitActive, ahk_pid %pid1%
SendInput This is the first instance of Word 2007, to be placed to the left side
sleep 1000
send #{Left}
sleep 100
WinActivate, ahk_pid %pid2%
WinWaitActive, ahk_pid %pid2%
SendInput This is the second instance of Word 2007, to be placed to the right side
sleep 1000
send #{Right}
sleep 100

msgbox "Hello--" %pid1% " , " %pid2%
ExitApp
The purpose of WinWait is to wait for the existence of a window with certain properties. If Internet Explorer refuses to start in a new second process it makes no sense to wait for this process. Word can be persuaded with /t to start in a new second process. I don't know how Internet Explorer can be persuaded to do this.
Perhaps this helps: https://autohotkey.com/board/topic/76227-resolved-run-does-not-retrieve-the-pid/
eagerahk
Posts: 122
Joined: 02 Dec 2015, 06:27

Re: Detecting multiple instances when using WinWait or WinActivate

05 Aug 2021, 19:56

Thank you, Rohwedder, for your endeavor! I tried here and stuck at the first loop where I always have ClassNN = ""

Code: Select all

Loop
{
	ControlGetFocus, ClassNN
	Sleep, 100
}
Until, ClassNN = _WwG1
Yes, it does help..after reading it and combine with my intensive tests, here are my observations:
  • PID is not 100% reliable, the only way to beat this problem is to place PID of WinActivate as close to Run command as possible. The following two examples demonstrate how PID is not countable.
Example1. Unliable PID if WinActivate is far away from the Run command

Code: Select all

run "iexplore" "d:\sample1.gif",,,pid1
loop 10
{sleep 100
WinActivate, ahk_pid %pid1%
if not errorlevel
	break
}
sleep 100
run "iexplore" "d:\sample2.gif",,,pid2
loop 10
{sleep 100
WinActivate, ahk_pid %pid2%
if not errorlevel
	break
}
sleep 100

WinActivate, ahk_pid %pid1%
sleep 100
send #{Left}
sleep 100

WinActivate, ahk_pid %pid2%
sleep 100
send #{Right}
sleep 100
msgbox "Hello--" %pid1% " , " %pid2%
ExitApp
Example2. Working example...PID is guaranteed to be useful only if WinActivate is as close to the Run command as possible

Code: Select all

run "iexplore" "d:\sample1.gif",,,pid1
loop 10
{sleep 100
WinActivate, ahk_pid %pid1%
if not errorlevel
	break
}
sleep 100
WinActivate, ahk_pid %pid1%
sleep 100
send #{Left}
sleep 100

run "iexplore" "d:\sample2.gif",,,pid2
loop 10
{sleep 100
WinActivate, ahk_pid %pid2%
if not errorlevel
	break
}
sleep 100
WinActivate, ahk_pid %pid2%
sleep 100
send #{Right}
sleep 100

msgbox "Hello--" %pid1% " , " %pid2%
ExitApp
  • The usefulness of WinWait is ambiguous, in the both working codes, example 2 and example 3, no WinWait is used. Also, Sleep time has been reduced to the minimum and without hard coding.
Example3. Working example...PID of WinActivate is as close to the Run command as possible; no WinWait, less Sleep amount and no hard coding.

Code: Select all

run "WINWORD.EXE" /t,,,pid1
loop 10
{sleep 100
WinActivate, ahk_pid %pid1%
if not errorlevel
	break
}
sleep 100
WinActivate, ahk_pid %pid1%
sleep 100
SendInput This is the first instance of Word 2007, to be placed to the left side
sleep 200
send #{Left}
sleep 100

run "WINWORD.EXE" /t,,,pid2
loop 10
{sleep 100
WinActivate, ahk_pid %pid2%
if not errorlevel
	break
}
sleep 100
WinActivate, ahk_pid %pid2%
sleep 100
SendInput This is the 2nd instance of Word 2007, to be placed to the right side
sleep 200
send #{Right}
sleep 100

msgbox "Hello--" %pid1% " , " %pid2%
ExitApp
Last edited by eagerahk on 05 Aug 2021, 22:44, edited 1 time in total.
eagerahk
Posts: 122
Joined: 02 Dec 2015, 06:27

Re: Detecting multiple instances when using WinWait or WinActivate

05 Aug 2021, 20:04

Example 4. Four PIDs working code

Code: Select all

run "iexplore" "d:\sample1.gif",,,pid1
loop 10
{sleep 100
WinActivate, ahk_pid %pid1%
if not errorlevel
	break
}
sleep 100
WinActivate, ahk_pid %pid1%
sleep 100
send #{Left}
sleep 100

run "iexplore" "d:\sample2.gif",,,pid2
loop 10
{sleep 100
WinActivate, ahk_pid %pid2%
if not errorlevel
	break
}
sleep 100
WinActivate, ahk_pid %pid2%
sleep 100
send #{Right}
sleep 500

run "WINWORD.EXE" /t,,,pid3
loop 10
{sleep 100
WinActivate, ahk_pid %pid3%
if not errorlevel
	break
}
sleep 100
WinActivate, ahk_pid %pid3%
sleep 100
SendInput This is the first instance of Word 2007, to be placed to the left side
sleep 200
send #{Left}
sleep 100

run "WINWORD.EXE" /t,,,pid4
loop 10
{sleep 100
WinActivate, ahk_pid %pid4%
if not errorlevel
	break
}
sleep 100
WinActivate, ahk_pid %pid4%
sleep 100
SendInput This is the 2nd instance of Word 2007, to be placed to the right side
sleep 200
send #{Right}
sleep 100

msgbox "Hello--" %pid1% " , " %pid2% " , " %pid3% " , " %pid4%
ExitApp
Rohwedder
Posts: 7550
Joined: 04 Jun 2014, 08:33
Location: Germany

Re: Detecting multiple instances when using WinWait or WinActivate

06 Aug 2021, 11:24

Your internetexplorer examples do not work for me. The two internetexplorer windows have the same pid ( = pid1).
However, if I open the first internetexplorer with an error, e.g. a non-existent image, the second one gets its own pid ( = pid2).
lexikos
Posts: 9552
Joined: 30 Sep 2013, 04:07
Contact:

Re: Detecting multiple instances when using WinWait or WinActivate

06 Aug 2021, 22:48

Both Word and Internet Explorer can be automated more reliably by using COM to both launch and control them, instead of Run and Win commands. I don't personally automate either program, but I would suggest checking the Tutorials forum.

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: Google [Bot] and 144 guests