如何自动化 UI 键盘输入? pywin32 PostMessage vs Powershell SendKeys

Posted

技术标签:

【中文标题】如何自动化 UI 键盘输入? pywin32 PostMessage vs Powershell SendKeys【英文标题】:How to automate UI keyboard input? pywin32 PostMessage vs Powershell SendKeys 【发布时间】:2020-08-21 22:21:11 【问题描述】:

动机:我正在使用一个没有 API 接口的软件......我别无选择,必须打开软件,发送简单的按键序列,然后关闭。 .. 一次又一次,所以我想自动化这个过程。

目标:将键盘输入组合发送到非活动窗口。

进度:我写了一个 powershell 脚本,它打开、发送密钥、等待,然后结束进程,但它只适用于活动窗口。部分powershell代码如下。

$appProcess = Start-Process -FilePath $path -PassThru 
$wshell = New-Object -ComObject wscript.shell;
$wshell.AppActivate($appProcess.Id)
$wshell.SendKeys('%(E)E')
Stop-Process $appProcess -Force

它有效,但仅在活动窗口上(窗口位于顶部)。我想要的是在后台自动运行窗口。我发现 an article 指向我在 Win32 API 中使用 PostMessage。由于我的大部分代码都使用 python,所以我决定从 powershell 迁移到 pywin32。

问题:我无法让 PostMessage 将密钥发送到正确的处理程序。我在this article 看到我可能需要找到确切的窗口,但我仍然不太明白如何。在 powershell 中,我可以直接通过 $wshell.AppActivate($appProcess.Id) 发送密钥。

hwndMain = win32gui.FindWindow(None, winname)
hwndChild = win32gui.GetWindow(hwndMain, win32con.GW_CHILD)
temp = win32api.PostMessage(hwndChild, win32con.WM_KEYDOWN, 0x45, 0)
# temp came out as None

问题:有没有办法在 pywin32 / Win32 API 中做到这一点?


编辑:(2020 年 5 月 8 日)是的,我听说使用 SendKeys 不可靠,但是由于在 SO 上没有提供类似问题的替代方案,所以任何人都应该如何学习“正确的方法”?如果您认为有其他选择,每个人都会很高兴看到解决方案在行动中。请建议对我的帖子进行修改,以提高问题的质量,而不是拒绝。

【问题讨论】:

查看winsourcecode.blogspot.com/2019/05/… 列出所有窗口。 winsourcecode.blogspot.com/2020/01/… 此处显示了一种更简单但不太可靠的方法。这是关于窗口而不是进程。您需要发送结果消息而不是密钥。 MS-DOS 不再存在。它已经有十多年没有存在了。 Windows 终端(命令)窗口不是 MS-DOS。 @KenWhite 感谢您的来信。我编辑了帖子以反映这一点。 @Mark 感谢您提供 2 个链接。我现在正在阅读它们。 "我发现一篇文章指出我在 Win32 API 中使用 PostMessage" - You can't simulate keyboard input with PostMessage 【参考方案1】:

前段时间我开发了SendMessage 实用程序,它允许通过WIN32 API 将消息发布到其他进程或Windows。我发现我无法向非活动窗口发送消息,所以我搜索了一种激活窗口的方法。经过几次测试,我发现了一个可以让我“重新激活”一个窗口的技巧:

这个程序的开发存在一个问题: 如果窗口未激活,则无法选择记事本最上面的菜单。 我做了一些测试,发现这一点取决于 cmd.exe 窗口与另一个窗口的关系(有?) 另一个窗口中的特定程序。例如,在这种情况下 计算器 Windows 附件的,它的菜单项可以选择时 窗口不活动,即使窗口最小化!一世 试图开发一种从 cmd.exe 激活其他窗口的方法 一种只使用系统定义的消息。我做了几个测试使用 WM_ACTIVATE、WM_CANCELMODE、WM_ENABLE 的多种组合, WM_ACTIVATEAPP、WM_SETFOCUS 和 WM_KILLFOCUS 消息,没有 成功。幸运的是,任何窗口的系统菜单中的项目都可以 从另一个窗口中选择,并在 SC_RESTORE 恢复后 窗口保持活动状态;这种行为可以激活 cmd.exe 中的记事本和其他窗口通过最小化/恢复 过程。

我认为使用我的 SendMessage.exe 实用程序,您可以测试是否可以将密钥发送到非活动窗口进程或激活它,因此您可以将这种方法转换为您的 phyton 代码。有关此问题的完整详细信息,请参阅this link。

【讨论】:

有一个特定的工具可以让您自动化 UI,而无需求助于不敬的黑客。它的名称为UI Automation。 UI 自动化并没有提出很多要求。例如,UI 自动化不要求目标处于活动状态、在前台,甚至不可见。 @IInspectable:我认为您在问题中忽略了这一行:问题:有没有办法在 pywin32 / Win32 API 中做到这一点?” i> 使用我的答案中提供的元素,OP 可以以一种非常简单的方式测试解决问题的 Win32 API 调用序列(将密钥发送到非活动窗口或重新激活非活动窗口),所以我认为我的答案回答发布的问题。恕我直言,您关于使用 UI 自动化工具的 建议 应该指向 OP,而不是指向我......这种情况值得否决吗?真的吗? :/ 对建议答案的投票计数对于未来寻求解决方案的访问者很有用。您的两种方法都无法交付。发送输入消息不能用于可靠地自动化 UI。并且建议通过强制窗口处于活动状态来更改先决条件并不能解决如何自动化不活动的 UI 的问题。这忽略了激活一个窗口是不够的。它也必须成为前台窗口,才能使用支持的输入输入方式接收输入。 @IInspectable 感谢您的评论...我以前从未听说过 UI 自动化 API! ...我知道我是新手。我一直在通过 SO 寻找与我的案例类似的解决方案,但我之前没有看到他们中的任何一个提到过这个 API。因此,我认为通过更多示例和解释,您可以为我的问题提供解决方案。是的,我多次听说使用 SendMessage 不可靠,但由于我的问题没有其他选择,任何人应该如何学习“正确的方法”?感谢您的评论,并希望看到实际的解决方案... @techtana 这不是不可靠的,它只是有规则。

以上是关于如何自动化 UI 键盘输入? pywin32 PostMessage vs Powershell SendKeys的主要内容,如果未能解决你的问题,请参考以下文章

UI自动化控制微信发送文件解决了一个无人回答的难题,Pywin32设置文件到剪切板

请教一个利用pywin32向特定窗口发送键盘消息的问题

po模型

po模型

用pywin32实现windows模拟鼠标及键盘动作

请用Python如何模拟键盘操作