app.focus() not working after window title change (Windows 8.1)?

Asked by Geoff Bache

I'm focussing on an application via its window title, but finding that further calls to focus() don't work after the app has changed window title. Basically what I want to do is return focus to the application under test after doing popup(). My application changes its window title somewhat frequently, and I'd prefer to be able to only put the initial title (which is reliable) in my script if I possibly can.

so

app = App.focus("Initial title")

... do stuff that cause the window title to change

if popAsk("Shall we continue?"):
    app.focus() # this does not work
   newApp = App.focus("new title") # this does work, but the new window title depends heavily on the current state
   ... do more stuff

app.close() # this does not seem to care about the title changes, and works anyway

I wonder if Sikuli has stored the initial window title and if app.focus() is looking for it again? That would explain why it doesn't work in this case.

Question information

Language:
English Edit question
Status:
Answered
For:
SikuliX Edit question
Assignee:
No assignee Edit question
Last query:
Last reply:

This question was reopened

Revision history for this message
RaiMan (raimund-hocke) said :
#1

the following example shows how one can use the tasklist command using run(someCommand).

It shows how you get the window title of the frontmost window of the requested app.

This title you can then use, to use App.focus("window title").

dir = r"c:\program files (x86)\notepad++" + "\\"
pgm = "notepad++.exe"

# the app should not run yet
# open app and get pid (process id)
appNP = App.open(dir + pgm)
pidNP = int(str(appNP).split("(")[-1].replace(")", ""))
print "Notepad PID:", pidNP
wait(3) # somehow wait until the window is ready

# use the tasklist command to get details about the app
cmd = 'tasklist /v /FO LIST /FI "IMAGENAME eq %s"' % (pgm)
result = run(cmd)
#print result # for debugging
temp = result.split("\r\n")
# temp[0] should contain "0" - the returncode of the command execution
# otherwise it failed

# evaluate the info
info = []
ni = 0
for n in range(len(temp)):
  if n == 0: continue # skip the return code
  e = temp[n].strip()
  if e == "": continue # skip empty lines
  parts = e.split(":") # get key/value
  info.append(parts[1].strip()) #store value
  #print parts[0], "(%d) ="%ni, info[-1] # for debugging
  ni += 1

appNP.close() # close the app

# show some app info
print 'app: %s (pid: %s) windowtitle: "%s"' % (info[0], info[1], info[-1])

"""
************** the output produced by this example using the debug prints
Notepad PID: 8480
[info] runcmd: tasklist /v /FO LIST /FI "IMAGENAME eq notepad++.exe"
0
Image Name: notepad++.exe
PID: 8480
Session Name: Console
Session#: 1
Mem Usage: 21,452 K
Status: Running
User Name: RAIMAN-PC\RaiMan
CPU Time: 0:00:00
Window Title: new 0 - Notepad++
Image Name (0) = notepad++.exe
PID (1) = 8480
Session Name (2) = Console
Session# (3) = 1
Mem Usage (4) = 21,452 K
Status (5) = Running
User Name (6) = RAIMAN-PC\RaiMan
CPU Time (7) = 0
Window Title (8) = new 0 - Notepad++
app: notepad++.exe (pid: 8480) windowtitle: "new 0 - Notepad++"
"""

hope it helps

Revision history for this message
Geoff Bache (geoff.bache) said :
#2

Yes, thanks, that gives some ideas, even if it's not all that beautiful a solution in that it requires dropping out of Python...

Would be good to add a note to the documentation for app.focus() if it assumes that "app" has not changed title since the object was created.

Revision history for this message
RaiMan (raimund-hocke) said :
#3

I just took the chance to revise the App class, so this all is done internally.

So this would work from tomorrow on:

app = App("some path to the app\someApp.exe")
app.open()
app.focus()

In this case the app.focus() will simply bring the app to the front with it's currently selected/frontmost window.

To select any other window by (part of the) title this still works:
app = App.focus("window title")
#do something
app.focus() # bring back this app to front with it's now may be different selected window.

This means, that an app object now on windows "knows" it's entry in the tasklist.

Revision history for this message
Geoff Bache (geoff.bache) said :
#4

Great, thanks. Will try it out tomorrow.

Revision history for this message
Geoff Bache (geoff.bache) said :
#5

Unfortunately I think there is some regression problem here.

App.focus("window title") does not work initially for me either now with last night's build. Switching the sikulixapi.jar back to my previous one (0420) works again. In the log it just says

[error] App.focus failed: [-1:window title ()] window title

But the window is present with that title, and it works with 0420.

Revision history for this message
RaiMan (raimund-hocke) said :
#6

be aware: the search for the window title with some part of it is now case sensitive.

a problem?

this is possible now (and is the recommended use and works)

--- open some application, bring it back to front later and close it

# creates an App object and checks, wether this app (theapp.exe) is already running (no action)

- using the path to the executable
someApp = App("<path to>/theapp.exe")

- using the name of the executable if found on system path (case does not matter)
someApp = App("notepad.exe")

- using part of the window title of a running app (case sensitive)
someApp = App("Part of the Title Text")

# open the app (if possible), if not already running and bring it to front
someApp.open()

# bring the app to front if it is running, otherwise use open()
someApp.focus()

# terminate the app
someApp.close()

--- additional new features (taken from task list command output)

# get the window title of the app's frontmost window
someApp.getWindow()

# get the process id
someApp.getPID() (-1 for a not running or not found app)

# get the name of the executable (image name)
someApp.getName()

--- the other features
openApp("….") is the same as
App.open("….") is the same as
App("….").open()

switchApp("….") is the same as
App.focus("….") is the same as
App("….").focus()

closeApp("….") is the same as
App.close("….") is the same as
App("….").close()

Revision history for this message
Geoff Bache (geoff.bache) said :
#7

Case sensitivity was not the problem.

What comes up initially in the application is a main window with a login screen in front of it. I had previously used the title of the login screen, which worked in 0420, as the main window has a non-ASCII "TM" superscript in the middle. By using your "tasklist" command above I found what that thinks the title is ("T" for "TM") and now I can focus on it initially. But app.focus() after the window title change still doesn't work (and doesn't log anything either).

I can try to rewrite to hand full control of the app's process to the Sikuli script (which is what the above implies), and see if that would work better. What I'm missing is a way to wait for the app to terminate, equivalent to process.wait() in Python's subprocess module, which is what I use right now. To complete my test I need to find various files written by the app, and for it to work reliably I need to know that the app is terminated. I guess I can check getPID() in a loop, but it doesn't feel very satisfactory...

Revision history for this message
Geoff Bache (geoff.bache) said :
#8

In fact, even the original code

App.focus("new title")

does not work any more with 0507. An app object is returned, no error is logged, but the window does not receive focus as it used to.

Revision history for this message
RaiMan (raimund-hocke) said :
#9

might have been misunderstandable:
- only in version 2015-05-08+ I think the problems are fixed.

The most reliable way, to get an APPLICATION back to front, now is, to create an App object in the beginning using

myApp = App("someText")

where someText can be either
1. the absolute path to an .exe
2. the name of an app, that can be found on the system path as someText.exe
3. part of the window title of an ALREADY RUNNING app

The version 3 only leads to a reliable app object in the case, that the application owning the given window can be started by only giving it's name (currently it is not yet evaluated, from where in the file system the app can be (re)started)

and then later only use myApp.open() or myApp.focus(), which should either focus the app with it's frontmost window or open it, if it is not already running (myApp must have been defined then with 1. or 2. of course).

... and a myApp setup() this way can be reliably closed using myApp.close(), which in the myApp object resets the pid to -1.
A later use of myApp.open() will reopen the app, since it still knows what .exe should be started.

With such an reliable app object you can check the running state using myApp.getPID(): if it is not -1, then it should be still running.

... and with such an reliable app object, with each myApp.focus() it is checked, wether the app is still running (checking the PID). If it is no longer running it will be reopened using the initially given information about the exe.

But of course there might still be quirks, since this App stuff is historically very inconsistent especially across the supported system versions. I am still on the way to make it more consistent, but the above mentioned things work.

BTW: in the 0507 version in fact App.focus("part of window title") did not work anymore.

One more thing:
If you use this way, after an myApp.open() or myApp.focus(), myApp.getWindow() returns the window title of the currently frontmost window of this app.

Revision history for this message
Geoff Bache (geoff.bache) said :
#10

I've just downloaded and installed last night's build (0512) and unfortunately the regression issues here seem to be worse/unchanged since 0507.

Neither a subsequent app.focus() nor a subsequent App.focus("part of current title") work in either 0507 or 0512, if I initially create the app in the third way by using part of the window title. As mentioned before, in both of these I have to use the name as given by tasklist, which can't be inferred from just looking at the window title, instead of the login dialog title which 0420 needed.

I can try to avoid the need for this by starting the app from Sikuli instead of via my script, as you describe, this will take a bit longer to test.

Another issue seems to have got worse, which is startup speed. I had a feeling 0507 took longer to get going than 0420, and some timing tests confirm this, but 0512 is *much* worse. I noticed that both 0507 and 0512 now write the message "[debug] KeyPress: WaitForIdle: false - Delay: 10", which 0420 does not. This looks like it adds a 10 second delay (the first action is typing the username into the login dialog). But strangely, running the same test repeatedly gives shorter delays than this in 0507, and longer in 0512.

0420: 15 seconds
0507: 19 seconds
0512: 38 seconds

All the extra time used is at the start. The only difference is the sikulixapi.jar used, and the text to find the app in the first place (which has to be different)

Incidentally, I couldn't find how to configure this 10 second delay, if such it is, is there a parameter?

Revision history for this message
Geoff Bache (geoff.bache) said :
#11

OK, I just discovered that testing setups (1) or (2) isn't possible, because I have to provide command line arguments in order to start my app (otherwise it can't find its server), so there is no way I can start the app from within Sikuli currently. There's a bug for this already, see

https://bugs.launchpad.net/sikuli/+bug/701363

So I'm reduced to starting it outside and then focussing on it, and then refocussing when needed.

Revision history for this message
RaiMan (raimund-hocke) said :
#12

ok, I am willing to bring back the parameter feature for App.open().

could you give me an example of your usage?

Revision history for this message
RaiMan (raimund-hocke) said :
#13

--- startup time
I will have a look into that. might have something to do with the new Jython version 2.7.0

Revision history for this message
RaiMan (raimund-hocke) said :
#14

--- "[debug] KeyPress: WaitForIdle: false - Delay: 10"
the 10 are milliseconds ;-)

I already noticed that, but this message should not come up.

Revision history for this message
Geoff Bache (geoff.bache) said :
#15

--parameters
There's nothing unusual about my app, it just needs some parameters on the command line to start properly. i.e.
c:\some\path\app.exe -server <server> -config <config> etc. I start it outside Sikuli using Python's subprocess module right now and then do App.focus().

--startup time
I'm still using the setup you recommended with my own Jython 2.5.3 installation, so it's not caused by Jython versions in my case.

Revision history for this message
RaiMan (raimund-hocke) said :
#16

-- parameters
with the build 2015-05-15+ you can do the following:

myApp = App(r"c:\some\path\app.exe")
myApp.setUsing("-server <server> -config <config>")

myApp.open() # internally CreateProcess is used now with c:\some\path\app.exe -server <server> -config <config>

the compact version works also:
myApp = App(r"c:\some\path\app.exe").setUsing("-server <server> -config <config>").open()

Would be nice, if you give it a try.

Revision history for this message
Geoff Bache (geoff.bache) said :
#17

Thanks. I'll take a look at this on Monday then.

Revision history for this message
RaiMan (raimund-hocke) said :
#18

Thanks and a nice weekend.

Revision history for this message
Geoff Bache (geoff.bache) said :
#19

Hmm, the app does not come up at all. It still works fine in the old way. No errors are written, and the exact command is the same.

Is Sikuli redirecting stdout and stderr from the app in the above example? Is there any way to debug this?

Revision history for this message
RaiMan (raimund-hocke) said :
#20

Does the app start as it should with the approach from comment #16?

if yes:
myApp.focus()

what happens?

Revision history for this message
Geoff Bache (geoff.bache) said :
#21

No it doesn't, that's what I'm reporting.

Revision history for this message
RaiMan (raimund-hocke) said :
#22

ok, found a problem. will be fixed tomorrow (bringing back the old behaviour additionally).

Sorry for the inconvenience.

Revision history for this message
Geoff Bache (geoff.bache) said :
#23

Afraid it's just the same as yesterday. It would be useful if I could somehow get some more info out myself. At the moment nothing is written and the app just doesn't come up. If there isn't any debug info in the area, perhaps some could be added?

Revision history for this message
RaiMan (raimund-hocke) said :
#24

Sorry for the delay.
Due to some other priorities I did not push the fix, so it is not in the current nightly.

I will do this within the next 3 hours, trigger a new build and give you a note, when it sis ready for you.

Revision history for this message
Geoff Bache (geoff.bache) said :
#25

Thanks!

Revision history for this message
RaiMan (raimund-hocke) said :
#26

ok, ready.
Latest available Build: 1.1.0 2015-05-19_12:04nightly

this works now on Windows:

# chrome to open a given webpage
cmd = r'"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" http://sikulix.com'

# using an App instance
bc = App(cmd)
print bc
if not bc.isRunning():
  bc.open()
wait(3)
bc.close()

# reusing the App instance but changing open parameters
bc.setUsing("http://sikulix.com/quickstart")
bc.open()
wait(3)
bc.close()
print bc

# using class methods
App.open(cmd)
wait(3)
# this works, because a running Chrome has the exe-name chrome.exe
App.close("chrome")

Thanks for insisting on a solution ;-)

Revision history for this message
Geoff Bache (geoff.bache) said :
#27

It's still not working for me.

I'm wondering if it's something to do with special characters in the arguments. Are you using the shell to start the process?
My actual argument is

config\serverurl=pipe://./xros15374x;config\auth_mode=local;

so either the backslashes or the semicolons might possibly be the cause of the problem?
Starting the same command from the same location using subprocess.Popen works fine.

Revision history for this message
Geoff Bache (geoff.bache) said :
#28

More info. You seem to be losing the first letter of the first argument! Here's the code

print cmd
app = App(cmd)
app.open()
app.focus()
#import subprocess
#proc = subprocess.Popen(cmd)
#app = App.focus(title)
print app

And here's what it prints

C:/work/ros-client/ros/build/cbxe2/bin/debug\ros.exe -LP -W config\serverurl=pipe://./xros11904x;config\auth_mode=local;
[9676:ros.exe (WEADDT ROS : (1936x1176))] C:/work/ros-client/ros/build/cbxe2/bin/debug\ros.exe LP -W config\serverurl=pipe://./xros11904x;config\auth_mode=local;

Note the lack of "-" before "LP" on your printout of "app" on the second line.

By putting a harmless argument here I can make it work. (I never got setUsing() to work by any method).
But the startup time is still too slow to use this in practice in any case...

Revision history for this message
RaiMan (raimund-hocke) said :
#29

ok, thanks.
the "first parameter character missing" is fixed. I will again trigger a build. ready latest in one hour.

--- I never got setUsing() to work by any method
this should work (since it does not loose the first character)

myApp = App(r"C:\work\ros-client\ros\build\cbxe2\bin\debug\ros.exe")
myApp.setUsing("-LP -W config\serverurl=pipe://./xros11904x;config\auth_mode=local;")
myApp.open()

--- But the startup time is still too slow to use this in practice in any case...
what time exactly are you talking about?

Revision history for this message
RaiMan (raimund-hocke) said :
#30

ok, thanks.
the "first parameter character missing" is fixed. I will again trigger a build. ready latest in one hour.

--- I never got setUsing() to work by any method
this should work (since it does not loose the first character)

myApp = App(r"C:\work\ros-client\ros\build\cbxe2\bin\debug\ros.exe")
myApp.setUsing("-LP -W config\serverurl=pipe://./xros11904x;config\auth_mode=local;")
myApp.open()

--- But the startup time is still too slow to use this in practice in any case...
what time exactly are you talking about?

Revision history for this message
Geoff Bache (geoff.bache) said :
#31

I reported the startup time regression in comment #10 above, and you promised to look into it in comment #13 :) I'm still using the build from 0420 in practice because of this issue.

The code you list above with setUsing doesn't work. I haven't been able to figure out exactly what goes wrong but the config file referenced via the last argument does not get found by the application.

Revision history for this message
RaiMan (raimund-hocke) said :
#32

--- startup time regression
yes I did, but forgot to answer on it:
the IDE startup time of the SikuliX IDE on my Windows 8.1 64-Bit is constantly at about 7 - 8 seconds.

--- setUsing not working
does this work from command line?
C:\work\ros-client\ros\build\cbxe2\bin\debug\ros.exe -LP -W config\serverurl=pipe://./xros11904x;config\auth_mode=local;

this is what is given to Win32API::CreateProcess

Revision history for this message
RaiMan (raimund-hocke) said :
#33

The new build is online.

Revision history for this message
Geoff Bache (geoff.bache) said :
#34

---- first parameter character missing
I can confirm that the first parameter character missing problem is now fixed. So the setup with providing the whole command line to the constructor now works.

---- subsequent app.focus() doesn't work
Unfortunately, the problem we set out to solve here doesn't work either though in this setup. I get an app object back, but "app.focus()" does not work later on when I try to return focus to the application after throwing up a dialog. As described before, the title of the app has changed by this point. No error is received, it just doesn't change the focus. Exactly as with the original setup where I created "app" via App.focus("initial title").

--- startup time regression
I'm not using the IDE, just the API jar. The additional time is taken between the app coming up and the first command (typing in the user name to the login dialog) being executed.

--- setUsing not working
Yes, that works, and it also works with the whole command line being sent to the app constructor as above. I don't need this to work now though as the constructor set up is just as good for my purposes.

Revision history for this message
RaiMan (raimund-hocke) said :
#35

--- startup time regression
Since it looks like you are using Jython scripting, but the sikulixapi.jar, you must have some Jython setup, that allows you to run the scripts.

How do you do that?

--- subsequent app.focus() doesn't work
could you either have a
print app
after the app.focus

or switch on Debug using
Debug.on(3)

to reveals some more info.
please post the relevant lines here.

Another option is, to issue a from command line the command:
tasklist /V /FO CSV /NH /FI "SESSIONNAME eq Console"

which produces the list that internally is now used for the support of the App features.
pleas post the line her, that contains your app.

Revision history for this message
Geoff Bache (geoff.bache) said :
#36

--- startup time regression
I'm not doing anything unexpected, and largely following your recommendations here.
I start Jython via

jython.bat -J-Xms64M -J-Xmx512M -Dfile.encoding=UTF-8 usecase.py <args_to_my_app>

and then in usecase.py I just do

import org.sikuli.basics.SikulixForJython # @UnusedImport
from sikuli import *

# Change some settings...

app = App(" ".join(sys.argv[1:]))
app.open()
app.focus()
type(...)

I can try and add some timing printouts and report back though.

--- subsequent app.focus() doesn't work
I've done all three things you suggested and attached the log file here. Some of the printouts are mine of course but I hope it's obvious where I try to return focus to the app, which doesn't work. The following search searches in the window which had focus anyway, and fails to find anything, obviously.

Revision history for this message
RaiMan (raimund-hocke) said :
#38

thanks for your patience, support and input.
I will do some tests again.

--- something else
[debug] JythonSupport: findModule: posixpath (null)
[debug] JythonSupport: loadModulePrepare: posixpath
[debug] ImagePath: add: /C:/jython2.5.3/Lib/posixpath.py # this is wrong and should not happen

there was a regression with the Jython import support for .sikuli stuff.
This is fixed now 2015-05-20+

Revision history for this message
Geoff Bache (geoff.bache) said :
#39

--- startup time regression
First observation: the penalty with the same setup seems to be reliably about 4 seconds again compared to 0420, i.e. as reported from 0507. The extreme slowdown observed with 0512 seems to be gone.

If I compare using the old way with App.focus(title), and just switch the sikulixapi.jar, it's clear that it is this App.focus call itself that adds this 4 second delay. It is essentially instantaneous with 0420 and takes 4 seconds with 0519.

If I switch to the new way as well, and start the app from within Sikuli, it seems to take 4 seconds to create the App object *and* 4 seconds to call app.open(). This leads to around an 8 second difference. I think this is because Jython also takes about this long to start, and by starting the app outside Sikuli this time runs concurrently to the app starting. Starting the app within Sikuli loses this parallelism unfortunately. So 4 of the seconds are possibly lost due to the same cause as above and 4 of them due to lost parallelism.
One workaround for the second of these problems would be to support App.focus(pid), then I could keep the parallelism while not needing to hardcode window titles in my scripts.

--- startup time regression
Thanks, I'll get hold of the latest version again then.

Revision history for this message
RaiMan (raimund-hocke) said :
#40

ok, some intermediate results (my machine: I7/3.4 16GB Win8.1/64)

I used your setup with Jython 2.5.4 running a test.py from command line with jython.bat

I used the same test with Version 1.0.1 and 1.1.0

import org.sikuli.basics.SikulixForJython
from sikuli import *

this is the SikuliX specific startup:
1.0.1: 1 sec
1.1.0: 1.5 sec
the additional time is due to the fact, that with version 1.1.0+ everything that is possible is done at startup

the App class features in version 1.0.1 run with "no" delay, but in 1.1.0 an open() and a focus() each costs about 1 second ( I will try to reduce this as much as possible).
BTW: after app.open() no additional app.focus() is needed.

The obvious problem:
in both versions an app.focus() with an App object setup with an app path, will bring the application to front, but will not activate the window to accept input.
This currently is only the case if you use App.focus("part of window title")

I will check an alternative solution and come back.

Revision history for this message
Geoff Bache (geoff.bache) said :
#41

--- subsequent app.focus() doesn't work
This sounds like it's caused by "The obvious problem" in your message above. It's necessary to activate the window as well as to bring it to the front. In future, App.focusedWindow() should return the right thing, i.e. the thing we tried to focus on.

--- startup performance regression
Can you run your test against 1.1.0 from mid-April (as close to the nightly from 0420 which I'm still using in practice)? That would be a more direct comparison. You could also maybe send me your test.py program. (my machine: I7-4800MQ/2.7 32GB Win 8.1/64)

Revision history for this message
RaiMan (raimund-hocke) said :
#42

--- subsequent app.focus() doesn't work
The next thing I will fix.

--- this is my test script:
import time
is10 = False
start = time.time()
try:
    import org.sikuli.script.SikulixForJython
except:
    is10 = True
    import org.sikuli.basics.SikuliXforJython
from sikuli import *
lap = time.time(); print "startup:", lap - start; start = lap
bc = App(r'"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe"')
if is10: bc.open()
lap = time.time(); print "App():", lap - start; start = lap
wait(1); click(); wait(1) # comment
start = time.time()
bc.focus()
lap = time.time(); print "App.focus:", lap - start; start = lap
wait(1); click(); wait(1) # comment
start = time.time()
bc.focus()
lap = time.time(); print "App.focus:", lap - start; start = lap
wait(2)
#bc.close()
App.focus("Google Chrome")
wait(2)
type(Key.F4, Key.ALT)

comment:
I am working on a 2 monitor system
Chrome opens on the 2nd monitor.
I use the click to the app in center of 1st monitor to "un-focus" chrome.
This might have to be adapted to your situation.

Revision history for this message
RaiMan (raimund-hocke) said :
#43

I think I fixed and optimized it:

- the cost for an open is now less than 0.5 seconds

- the cost for focus is some 10 millisecs

- focus now activates the foreground window after bringing it to front.

this is tested with the before mentioned test script (without the final App.focus("Google Chrome"))

I will trigger a build, that should be ready within 1 h

Revision history for this message
Geoff Bache (geoff.bache) said :
#44

I just installed last night's nightjob. Did the changes get pushed? The subsequent app.focus() still doesn't work (it doesn't bring the window to the front or activate it) and the performance improvement is barely noticeable (it's possibly very slightly better but it's still reliably several seconds slower than 0420, with both ways of creating the app)

Revision history for this message
RaiMan (raimund-hocke) said :
#45

I just made an IDE setup with the last nightly 2015-05-21-0100 (Win7 and Win8 both 64-Bit)

the SikuliX stuff init takes about 1.5 seconds (was 1 sec with 1.0.1)

the focus works and activates the window (takes less than 0.1 sec)

the open adds less than 0.5 seconds.

So I have no idea, what the problem is on your side.

Revision history for this message
Geoff Bache (geoff.bache) said :
#46

I did some more experimenting. I downloaded the latest nightjob and used your script above and more or less replicated the results I got with my own app last week.
There is a fairly constant 1.2 second penalty for using the latest version instead of 0420 when creating or focussing on a new app.
The later app.focus always works with 0420 and usually, though not always, doesn't with 0524: I invariably have to close the latter myself by hand. Here's my logs, same script as posted above. My machine details are also posted above, but they seem to be the same as yours. I'm using Java 8 (jre1.8.0_45) if that's relevant.

The original version from April:

D:\tmp>SET CLASSPATH=C:/Users/e601429/sikulix0420/sikulixapi.jar

D:\tmp>C:\jython2.5.3\jython.bat -J-Xms64M -J-Xmx512M -Dfile.encoding=UTF-8 testsik.py
startup: 1.54699993134
App(): 0.00200009346008
[log] CLICK on L(960,540)@S(0)[0,0 1920x1080]
[log] App.focus "C:\Program Files (x86)\Google\Chrome\Application\chrome.exe"(0) #0
App.focus: 0.0160000324249
[log] CLICK on L(960,540)@S(0)[0,0 1920x1080]
[log] App.focus "C:\Program Files (x86)\Google\Chrome\Application\chrome.exe"(524) #0
App.focus: 0.000999927520752
[log] App.focus Google Chrome(0) #0
[log] ( Alt ) TYPE "#F4."

The newest nightjob:

D:\tmp>SET CLASSPATH=C:/Users/e601429/sikulix0524/sikulixapi.jar

D:\tmp>C:\jython2.5.3\jython.bat -J-Xms64M -J-Xmx512M -Dfile.encoding=UTF-8 testsik.py
startup: 1.19600009918
App(): 1.17499995232
[log] CLICK on L(960,540)@S(0)[0,0 1920x1080]
[log] App.focus: [6616:chrome.exe]
App.focus: 0.120000123978
[log] CLICK on L(960,540)@S(0)[0,0 1920x1080]
[log] App.focus: [6616:chrome.exe]
App.focus: 0.105000019073
[log] App.focus: [6616:chrome.exe]
[log] ( Alt ) TYPE "#F4."

Revision history for this message
RaiMan (raimund-hocke) said :
#47

The Java version does not matter in this case.

I will again check, but currently I have no idea, why the elapsed times on your side are all doubled against my situation.
I cannot really imagine, that this is because you use Jython 2.5.3 (I use 2.5.4 and 2.7.0)

That the Alt-F4 does not work in all cases is surely a timing problem.
a short wait(0.5) before should fix that.

You can get rid of the startup addon time by using
app = App.open(....)

... but this does not check the process list and opens a new app instance in all cases (as did 1.0.1 and 1.1.0 until I revised this feature in 2015-05).

Revision history for this message
Geoff Bache (geoff.bache) said :
#48

OK, the App.open(...) tip seems to work to avoid the startup time penalty (and needs documenting...). That's really the only performance problem, that the other takes 0.1 seconds instead of 0.01 isn't significant in the scheme of things. So it's more why the focus isn't working now.

But also, there is a new problem unfortunately. Yesterday's nightjob does not find images which last week's (0519) has no problem with. Has something changed in this area?

Revision history for this message
Geoff Bache (geoff.bache) said :
#49

Another thing to note is that if I change your script above to use App.open(...) instead of App(...).open(), I get several instances of Chrome started, the subsequent app.focus() calls seem to start new instances instead of focusing on the one I have! Something seems very wrong with app.focus() right now.

Revision history for this message
RaiMan (raimund-hocke) said :
#50

--- does not find images which last week's (0519) has no problem with.
I added some new features to the class Region, but that should not have any consequences like you are saying.

Is this for all images or only for some?

Does finding images work at all?

Revision history for this message
RaiMan (raimund-hocke) said :
#51

the App problem: I will check.

Revision history for this message
Geoff Bache (geoff.bache) said :
#52

On closer examination, the reason 0524 is not finding the images in question seems to be because App.focusedWindow() is returning the wrong thing (and hence we're searching in the wrong place). It seems to continue to return the dimensions of the original focused window (the login dialog) long after the login dialog has ceased to be shown.

Revision history for this message
Geoff Bache (geoff.bache) said :
#53

And on even closer examination, it seems to be my fault. The timing is changed, and I'm caching the focused window when I shouldn't be. Sorry about that.

Remaining problem is app.focus() not working, and nothing else :)

Revision history for this message
RaiMan (raimund-hocke) said :
#54

ok, thanks for this additional information.

I am already nearly finished with the fix of focus() (a stupid regression due to bringing back the fast open() ;-)

Revision history for this message
RaiMan (raimund-hocke) said :
#55

ok, I think I have fixed it now, so that focus() should work in all situations.

available with tomorrows build (2015-05-28)

Revision history for this message
Geoff Bache (geoff.bache) said :
#56

Just installed the nightly build, but I still get the same problem (with your script above, modified to use App.open as suggested, I get 3 Chrome instances of which only one gets closed). Have you tested this?

(Sometimes I wonder a bit if all these installations I keep making from nightly builds are actually independent of each other...)

Revision history for this message
RaiMan (raimund-hocke) said :
#57

--- if all these installations I keep making from nightly builds are actually independent of each other
yes, they are.

besides your Chrome experience (I meanwhile have a more complex test script and will again have a look), what about your app (which was the original challenge)?

Revision history for this message
Geoff Bache (geoff.bache) said :
#58

My app doesn't work either (subsequent focus does not bring it to the front or activate it).

Revision history for this message
RaiMan (raimund-hocke) said :
#59

ok, still not working in all cases.

a current workaround, to just see how it "could" work:
before issuing a follow-up myApp.focus() add a
print myApp

(this is why MY tests are working ;-)

Revision history for this message
Geoff Bache (geoff.bache) said :
#60

Hmm, I have a printout like that too, although it says

print "About to focus on", myApp

which presumably has the same effect? It doesn't seem to help me.

Revision history for this message
RaiMan (raimund-hocke) said :
#61

No idea, what that does not work for you.

But anyway: I have it now running without any hacks ;-)

my test scripts (if interested):

the Chrome test:
https://github.com/RaiMan/SikuliX-2014/tree/master/StuffContainer/testScripts/testApp/testTiming.sikuli

a test with a 1-window application
https://github.com/RaiMan/SikuliX-2014/tree/master/StuffContainer/testScripts/testApp/testApp.sikuli

I triggered a build, that should be ready in a few minutes.

I still have to revise the docs a bit.

Revision history for this message
Geoff Bache (geoff.bache) said :
#62

The good news: the Chrome based test script now works for me.
The bad news: my app still doesn't. Same symptoms as before. "print app" does not help.

I wondered about trying to use app.window() instead of App.focusedWindow() as a workaround to find the correct window to search in even when the app was not in focus, but that seems to largely return nonsense for me. It also seems to retain window references there long after they have ceased to be visible.

Here's what it returned, when my app has 1 active window, filling the whole screen (1920x1200). Note that also it doesn't return None at all, but keeps returning the same window if you keep increasing the index.

0 R[104,104 943x89]@S(0)[0,0 1920x1200] E:Y, T:3,0
1 R[346,334 815x495]@S(0)[0,0 1920x1200] E:Y, T:3,0
2 R[346,334 815x495]@S(0)[0,0 1920x1200] E:Y, T:3,0
3 R[346,334 815x495]@S(0)[0,0 1920x1200] E:Y, T:3,0
4 R[346,334 815x495]@S(0)[0,0 1920x1200] E:Y, T:3,0
5 R[346,334 815x495]@S(0)[0,0 1920x1200] E:Y, T:3,0
6 R[346,334 815x495]@S(0)[0,0 1920x1200] E:Y, T:3,0
7 R[346,334 815x495]@S(0)[0,0 1920x1200] E:Y, T:3,0
8 R[346,334 815x495]@S(0)[0,0 1920x1200] E:Y, T:3,0
9 R[346,334 815x495]@S(0)[0,0 1920x1200] E:Y, T:3,0

Revision history for this message
RaiMan (raimund-hocke) said :
#63

coming back to the initial question, then I think, this should work now with your app

- start it outside Sikuli using Python's subprocess module right now (you mentioned before)

- then in the script:
app = App.focus("part of initial window title")
print app

# actions, that change the window title
app.focus() # should bring the app to front
print app

so that App.focusedWindow() should work.

the print app are only to check, how we see the app currently in the process list.

The alternative to the outside start should be using
app = App.open(r'"path-to-your.exe" parameters for your app')

--- the never ending window list
... is completely unusual
On Windows many applications have sometimes 10 or more windows defined, that are not visible (either outside the screen or set invisible). This is currently not detected by the implementation of the Win32 API calls. So you have to do some filtering, to get the most probable window.

... but never before I have seen this situation, that the same window area is mentioned more than 1 or 2 times.

... and since you are saying, that the visible window fills the screen (with 1920x1200), then it is strange, that this window is not in your list of the first 10 windows.

Revision history for this message
Geoff Bache (geoff.bache) said :
#64

Unfortunately this setup, after starting via App.focus("part of window title"), app.focus() doesn't work there either :(

If you don't have any more ideas as to what the cause could be then I guess I'll just have to build Sikuli myself and debug it, sometime when I have a bit more time to devote to this...

Revision history for this message
RaiMan (raimund-hocke) said :
#65

Might have been misunderstanding:

simply like that

-- start your app however you want and then run a script like this:

app = App.focus("part of initial window title")
print app

# actions, that change the window title
# and bring any other non-app window to front

app.focus() # should bring the app back to front
print app

Revision history for this message
Geoff Bache (geoff.bache) said :
#66

No, that's what I did. And it doesn't work for me.

Revision history for this message
RaiMan (raimund-hocke) said :
#67

could you post the output of the 2 "print app" ?

additionally the output of (after the second focus):
App.getApps("ros.exe")

if this is still the app we are talking about

Revision history for this message
Geoff Bache (geoff.bache) said :
#68

Here's my log. Hope you can make sense of what is what.

10:54:59.793999 : [10840:ros.exe (WEADDT ROS : (1936x1176))] WEADDT ROS
10:55:00.%f : Searching for Beställningsöversikt in R[0,0 1920x1168]@S(0)[0,0 1920x1200] E:Y, T:1,0 timeout= 1
[error] Image: could not be loaded: file:/C:/TT/roscl.29May105450.11340/roscl/Minimal/LIO/RosClient/PDL/SingleUnitOrders/SameCareUnit/Best孬nings��sikt.png
10:55:01.%f : Failed to find Beställningsöversikt in R[0,0 1920x1168]@S(0)[0,0 1920x1200] E:Y, T:1,0
Giving up!
[10840:ros.exe (WEADDT ROS : Liten testdatabas / Klient: 3.6.3.0)] WEADDT ROS
Focused on [10840:ros.exe (WEADDT ROS : Liten testdatabas / Klient: 3.6.3.0)] WEADDT ROS
10840:ros.exe (WEADDT ROS : Liten testdatabas / Klient: 3.6.3.0)
App.getApps: 1 apps (1 having window)
None
10:55:15.%f : Found image region for Beställningsöversikt = M[1583,737 125x19]@S(S(0)[0,0 1920x1200]) S:1,00 C:1645,746 [41/33 msec]
Hint Area was R[1480,549 346x325]@S(0)[0,0 1920x1200] E:Y, T:3,0
10:55:25.%f : Found image region for Arkiv = M[4,25 33x15]@S(S(0)[0,0 1920x1200]) S:1,00 C:20,32 [18/16 msec]
Hint Area was R[7,28 27x9]@S(0)[0,0 1920x1200] E:Y, T:3,0
10:55:25.%f : Found image region for Avsluta = M[32,77 44x15]@S(S(0)[0,0 1920x1200]) S:0,99 C:54,84 [16/12 msec]
Hint Area was R[32,77 44x15]@S(0)[0,0 1920x1200] E:Y, T:3,0

Revision history for this message
RaiMan (raimund-hocke) said :
#69

--- this seems to be the print app after the initial focus()
10:54:59.793999 : [10840:ros.exe (WEADDT ROS : (1936x1176))] WEADDT ROS

--- this seems to be the print app after the followup focus()
Giving up!
[10840:ros.exe (WEADDT ROS : Liten testdatabas / Klient: 3.6.3.0)] WEADDT ROS

as we can see, the window text is updated.

--- this is the report from getApps()
App.getApps: 1 apps (1 having window)

which confirms, that only one process "ros.exe" exists, which has a main window

--- after that there is 3 times a message like
... Found image region for ...

which I interpret such that the window at least is visible.

So if you managed to get the window hidden after the first focus somehow, then apparently the second focus must have brought it back to front ????

Revision history for this message
Geoff Bache (geoff.bache) said :
#70

I'm afraid I clicked in the window by hand, so that the test could proceed. Sorry for the confusion. Up until the "1 apps" message you can rely on things. If I hadn't intervened it would have just hung there.

Revision history for this message
RaiMan (raimund-hocke) said :
#71

ok, thanks.
nice weekend.

Revision history for this message
Geoff Bache (geoff.bache) said :
#72

I think you misunderstood. That doesn't mean there wasn't a problem. It just means it was easier to get it to complete by helping it along after the focus failed than killing it. Here's the log you should be concerned about:

10:54:59.793999 : [10840:ros.exe (WEADDT ROS : (1936x1176))] WEADDT ROS

..... stuff that causes the focus to change

[10840:ros.exe (WEADDT ROS : Liten testdatabas / Klient: 3.6.3.0)] WEADDT ROS
Focused on [10840:ros.exe (WEADDT ROS : Liten testdatabas / Klient: 3.6.3.0)] WEADDT ROS
10840:ros.exe (WEADDT ROS : Liten testdatabas / Klient: 3.6.3.0)
App.getApps: 1 apps (1 having window)

Revision history for this message
RaiMan (raimund-hocke) said :
#73

no, I did not misunderstand ;-)

You explained, why there where successful finds and hence I had to accept, that it is still not working on your side with your app.
The interpretation of your log output was totally clear to me.

all this I wanted to signal with:
ok, thanks.
nice weekend.

… means also, that I will not do anything with this problem before Monday, sorry.

Revision history for this message
Geoff Bache (geoff.bache) said :
#74

OK, I see. Launchpad told me you "proposed this answer", which led me to believe you thought I'd retracted the problem.

Thanks for your efforts and a nice weekend to you too :)

Revision history for this message
RaiMan (raimund-hocke) said :
#75

ok.

Revision history for this message
RaiMan (raimund-hocke) said :
#76

back on Monday ;-)

Revision history for this message
RaiMan (raimund-hocke) said :
#77

I still found some issues, after having tested with a workflow like yours.

App.open("program parameters")
myApp = App.focus("startup title")

# focus switched away
# actions to change window title

myApp.focus() # brings back focus :-)

hope it works now for you too.

The new build should be available in a few minutes.

Revision history for this message
Geoff Bache (geoff.bache) said :
#78

I'm afraid it still doesn't work for me. This with yesterday's nightjob (0601_2300). Tried both with App.open("...") and App.focus("startup title").

Revision history for this message
Geoff Bache (geoff.bache) said :
#79

As this seems to have stopped, I wonder if you could send me the actual command/API call you use to focus a given window? That might allow me to debug why it's not working for me without needing to build everything, single-step etc.

Revision history for this message
RaiMan (raimund-hocke) said :
#80

sorry for the delay - had some private priorities - and still have.

Tomorrow's build will have a few changes.

Later I will give you the link to the test script I use currently

Revision history for this message
Geoff Bache (geoff.bache) said :
#81

OK, no problem at all of course.

I'd still like to get a local build working, I think it might greatly speed up discovering what my problem actually is. I guess I'll ask a new question about that though to avoid clogging this one further...

Revision history for this message
Geoff Bache (geoff.bache) said :
#82

Hi again. Are you working with Sikuli again now? Would still appreciate a link to the test script promised above, or the API call used to focus windows, or some kind of answer as to why the local build isn't working (separate question
https://answers.launchpad.net/sikuli/+question/267930 which expired due to no attention for 15 days).

Thanks for your work with Sikuli.

Revision history for this message
RaiMan (raimund-hocke) said :
#83

ok, I will come back on that asap.

Can you help with this problem?

Provide an answer of your own, or ask Geoff Bache for more information if necessary.

To post a message you must log in.