9

Working on the Python-powered automation tool.

Imagine there is a pool of apps running:

APPS_POOL = ['Chrome', 'SomeApp', 'Foo']

The script runs in the loop (every second) and needs to switch randomly between them:

# Init App object
app = application.Application()

# Select random app from the pull of apps
random_app = random.choice(APPS_POOL)
app.connect(title_re=".*%s" % random_app)
print 'Select "%s"' % random_app

# Access app's window object
app_dialog = app.window_(title_re=".*%s.*" % random_app)

if app_dialog.Exists():
    app_dialog.SetFocus()

The first time it works fine, but every other - the window would not be brought into foreground. Any ideas?

EDIT: the script is ran from Win7 CMD. Is it possible the system "blocks" CMD from setting focus somehow, once focus is set to other window?

0leg
  • 13,464
  • 16
  • 70
  • 94

4 Answers4

14

I think the SetFocus is a bit buggy. At least on my machine I get an error: error: (87, 'AttachThreadInput', 'The parameter is incorrect.'). So maybe you can play with Minimize/Restore. Notice that this approach is not bullet proof either.

import random
import time
from pywinauto import application
from pywinauto.findwindows import WindowAmbiguousError, WindowNotFoundError

APPS_POOL = ['Chrome', 'GVIM', 'Notepad', 'Calculator', 'SourceTree', 'Outlook']


# Select random app from the pull of apps
def show_rand_app():
    # Init App object
    app = application.Application()

    random_app = random.choice(APPS_POOL)
    try:
        print 'Select "%s"' % random_app
        app.connect(title_re=".*%s.*" % random_app)

        # Access app's window object
        app_dialog = app.top_window_()

        app_dialog.Minimize()
        app_dialog.Restore()
        #app_dialog.SetFocus()
    except(WindowNotFoundError):
        print '"%s" not found' % random_app
        pass
    except(WindowAmbiguousError):
        print 'There are too many "%s" windows found' % random_app
        pass

for i in range(15):
    show_rand_app()
    time.sleep(0.3)
vitswd
  • 449
  • 1
  • 5
  • 8
7

above one is perfect answer, however HasStyle is deprecated the new method is as below

if m.has_style(win32defines.WS_MINIMIZE): # if minimized
    ShowWindow(m.wrapper_object(), 9) # restore window state
else:
    SetForegroundWindow(m.wrapper_object()) #bring to front

...... another way of dealing..

app = Application(backend='win32').connect(path="")
app.top_window().set_focus()
Waterworks
  • 308
  • 4
  • 11
3

As included in this issues

https://github.com/pywinauto/pywinauto/issues/785

SetForegroundWindow function has been deprecated in certain pywinauto version < 0.6.7 module. They've suggested to use .set_focus() in that blog

app = Application(backend='uia').start(app_path)
app.top_window().set_focus()

or else suggested to use win32 module SetForegroundWindow function where even pywinauto using the same function in background.

import win32gui 
app = Application(backend='uia').start(app_path)
shell = win32com.client.Dispatch("WScript.Shell")
shell.SendKeys('%')
win32gui.SetForegroundWindow(app.top_window().handle)

In above mentioned code we can't use win32gui.SetForegroundWindow just like that before invoking that function we need to send alt key function so that win32gui.SetForegroundWindow function works properly and set application window to foreground.

Reference: https://www.codetd.com/en/article/7238534

Jaikishore
  • 111
  • 2
  • 6
  • I have tried this but getting `No windows for that process could be found` error. My code is as follows: `from pywinauto.application import Application, win32defines from pywinauto.win32functions import ShowWindow import win32gui, win32com.client def setup(): app=Application(backend="uia") app.connect(path="C:\\Program Files\\MetaTrader 5\\terminal64.exe") shell = win32com.client.Dispatch("WScript.Shell") return app, shell app, shell = setup() shell.SendKeys('%') win32gui.SetForegroundWindow(app.top_window().handle)` – Andy Thompson Aug 31 '21 at 14:31
  • @AndyThompson Can you please paste your code in pastebin.com so that i can take look at in a clear manner. – Jaikishore Sep 01 '21 at 16:38
  • @AndyThompson I have the same issue as you. Did you find the answer? – kanjas May 23 '22 at 11:50
1

Accepted answer didn't work properly in some cases - some apps based on Qt4-5 don`t load there GUI properly in some reason. So, i found another workaround of SetFocus() bug.

from pywinauto import Application, win32defines
from pywinauto.win32functions import SetForegroundWindow, ShowWindow

app = Application().connect(path="C:\path\to\process.exe")
w = app.top_window()

#bring window into foreground
if w.HasStyle(win32defines.WS_MINIMIZE): # if minimized
    ShowWindow(w.wrapper_object(), 9) # restore window state
else:
    SetForegroundWindow(w.wrapper_object()) #bring to front
heyzling
  • 306
  • 2
  • 4