Pywinauto:无法将窗口置于前台

9

我正在开发一个由Python驱动的自动化工具。

想象一下有一堆应用程序在运行:

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

脚本在循环中运行(每秒一次),需要在它们之间随机切换:
# 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()

第一次它可以正常工作,但是之后每次都无法将窗口置于前景。有什么想法吗?
编辑:脚本是从Win7 CMD运行的。一旦焦点设置为其他窗口,系统是否会以某种方式“阻止”CMD设置焦点?
4个回答

14

我认为SetFocus有点bug。 至少在我的机器上,我会收到一个错误: 错误:(87,“AttachThreadInput”,“参数不正确”)。 所以也许你可以尝试最小化/恢复。 请注意,这种方法也不是完全可靠的。

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,它有效了!看起来Focus()确实有漏洞。此外,使用try..except是个不错的举措。 - 0leg
只是好奇,你是怎么收到这个错误的(控制台,你尝试过调试吗)? - 0leg
我在IPython中玩了一下你的代码,当SetFocus失败时,我看到了上面的错误。 - vitswd
当窗口置顶时,是否有任何调整窗口大小的选项? - Keyur Vala

7

上面的回答是完美的,但是HasStyle已经弃用了,新的方法如下:

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()

3

本问题已包含在此链接中。

SetForegroundWindow函数在某些pywinauto版本<0.6.7模块中已被弃用。他们建议在该博客中使用.set_focus()代替。

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

建议使用win32模块中的SetForegroundWindow函数,即使pywinauto也在后台使用同一函数。
import win32gui 
app = Application(backend='uia').start(app_path)
shell = win32com.client.Dispatch("WScript.Shell")
shell.SendKeys('%')
win32gui.SetForegroundWindow(app.top_window().handle)

在上面提到的代码中,我们不能像那样直接使用win32gui.SetForegroundWindow函数,在调用该函数之前需要发送alt键函数,以便win32gui.SetForegroundWindow函数正常工作并将应用程序窗口置于前景。
参考:https://www.codetd.com/en/article/7238534

我已经尝试过了,但是出现了“找不到该进程的窗口”错误。我的代码如下: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
@AndyThompson,您能否将您的代码粘贴到pastebin.com上,这样我可以清晰地查看它。 - Jaikishore
@AndyThompson 我和你一样遇到了同样的问题。你找到答案了吗? - kanjas

1

有些情况下,接受的答案不能正常工作 - 一些基于Qt4-5的应用程序在某些情况下无法正确加载其GUI。因此,我找到了另一个解决SetFocus()错误的方法。

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

正确。我在Qt5应用程序(WireShark)中看到了这个问题。将在pywinauto 0.6.4中修复。 - Vasily Ryabov

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接