在 Matlab 中启动 .exe 文件后以编程方式按回车键
programmatically press an enter key after starting .exe file in Matlab
在 Matlab 中,我可以启动外部 .exe 文件,这些文件有时会弹出一个要求按下回车键的窗口。例如:
system('C:\Program Files (x86)\WinZip\WINZIP32.EXE')
将启动 Winzip,然后为了使用它,您需要按回车键通过 "buy now" 弹出 window。
现在我的问题不在于 winzip,我只是举个例子(反正我用的是 winrar :)。
在这种情况下,如何以编程方式在 Matlab 中按下回车键? (我用的是win 7)
可以使用事件侦听器来解决这个问题吗?
编辑:java.awt.Robot class 确实适用于资源管理器,但不适用于任何弹出 window 且需要按下确定按钮的软件。我不知道为什么它不起作用。我给出了 winzip 示例,因为我假设每个人都在他们的机器上安装了 winzip/winrar。我拥有的实际软件与问题不同且无关。
有一种方法可以使用来自 Matlab 的 Java,特别是 java.awt.Robot
class。参见 here。
显然有两种类型的程序,关于它们在使用 system('...')
从 Matlab 调用时的工作方式:
对于某些程序,Matlab 等待 直到程序在 运行 下一条语句之前完成。例如 WinRAR
(至少在我的 Windows 7 机器上)会发生这种情况。
对于其他程序,这不会发生,Matlab 在外部程序启动后立即继续执行下一条语句。这种类型的一个例子是 explorer
(标准的 Windows 文件浏览器)。
现在,即使对于类型 1 程序,也可以 return 立即执行到 Matlab:只需在传递给 system
的字符串末尾添加 &
。这是standard in Linux Bash shell, and it also works in Windows, as discussed here。
因此,您将按如下方式进行:
robot = java.awt.Robot;
command = '"C:\Program Files (x86)\WinRAR\WinRAR"'; %// external program; full path
system([command ' &']); %// note: ' &' at the end
pause(5) %// allow some time for the external program to start
robot.keyPress (java.awt.event.KeyEvent.VK_ENTER); %// press "enter" key
robot.keyRelease (java.awt.event.KeyEvent.VK_ENTER); %// release "enter" key
如果您的应用程序仅在 Windows 平台上,您可以尝试使用 .net
个对象。
SendKeys
对象的 SendWait
方法允许将几乎任何键或键组合发送到具有焦点的应用程序,包括 "modifier" 键,如 Alt、Shift、Ctrl 等...
首先要做的是导入 .net
库,然后发送 ENTER 键的完整语法为:
NET.addAssembly('System.Windows.Forms');
System.Windows.Forms.SendKeys.SendWait('{ENTER}'); %// send the key "ENTER"
如果您只在完整语法确定后才这样做。如果您打算广泛使用该命令,您可以使用匿名辅助函数帮助自己。
记事本的一个小例子
%% // import the .NET assembly and define helper function
NET.addAssembly('System.Windows.Forms');
sendkey = @(strkey) System.Windows.Forms.SendKeys.SendWait(strkey) ;
%% // prepare a few things to send to the notepad
str1 = 'Hello World' ;
str2 = 'OMG ... my notepad is alive' ;
file2save = [pwd '\SelfSaveTest.txt'] ;
if exist(file2save,'file')==2 ; delete(file2save) ; end %// this is just in case you run the test multiple times.
%% // go for it
%// write a few things, save the file then close it.
system('notepad &') ; %// Start notepad, without matlab waiting for the return value
sendkey(str1) %// send a full string to the notepad
sendkey('{ENTER}'); %// send the {ENTER} key
sendkey(str2) %// send another full string to the notepad
sendkey('{! 3}'); %// note how you can REPEAT a key send instruction
sendkey('%(FA)'); %// Send key combination to open the "save as..." dialog
pause(1) %// little pause to make sure your hard drive is ready before continuing
sendkey(file2save); %// Send the name (full path) of the file to save to the dialog
sendkey('{ENTER}'); %// validate
pause(3) %// just wait a bit so you can see you file is now saved (check the titlebar of the notepad)
sendkey('%(FX)'); %// Bye bye ... close the Notepad
如 Microsoft 文档中所述,SendKeys
class 有时可能会出现一些计时问题,因此如果您想进行复杂的操作(例如 Tab 多次更改您实际想要按下的按钮),您可能必须在对 SendKeys
.
的 Matlab 调用中引入 pause
不先尝试,但不要忘记您是在管理另一个进程,而它们之间没有任何同步,因此在正确安排之前可能需要反复试验所有时间,至少对于复杂的序列而言(简单的应该是直截了当的)。
以我上面的例子为例,我运行我所有的数据都来自一个外部硬盘驱动器,它具有ECO功能,可以让它进入待机状态,所以当我调用"save as..." 对话框,它需要一些时间才能显示,因为 HDD 必须唤醒。如果我不引入pause(1)
,有时文件路径会不完整(路径的第一部分在对话框获得焦点之前发送).
另外,执行外部程序时不要忘记&
字符。所有功劳都归功于 Luis Mendo 对它的强调。 (我往往会忘记它的重要性,因为我默认使用它。只有当我必须专门等待程序中的 return 值时,我才会省略它,否则我会 let it run on its own)
特殊字符有特殊代码。这里有一些:
Shift +
Control (Ctrl) ^
Alt %
Tab {TAB}
Backspace {BACKSPACE}, {BS}, or {BKSP}
Validation {ENTER} or ~ (a tilde)
Ins Or Insert {INSERT} or {INS}
Delete {DELETE} or {DEL}
Text Navigation {HOME} {END} {PGDN} {PGUP}
Arrow Keys {UP} {RIGHT} {DOWN} {LEFT}
Escape {ESC}
Function Keys {F1} ... {F16}
Print Screen {PRTSC}
Break {BREAK}
可以找到 Microsoft 的完整列表 here
Python 包 pywinauto 可以等待任何对话框并自动单击按钮。但它仅适用于本机和某些 .NET 应用程序。您可能在按下 WPF 按钮时遇到问题(也许 QT 按钮是可点击的 - 未选中),但在这种情况下,像 app.DialogTitle.wait('ready').set_focus(); app.DialogTitle.type_keys('{ENTER}')
这样的代码可能会有所帮助。您的情况非常简单,可能使用 pywinauto 的一些技巧就足够了。你的 "app with popup" 是 64 位还是 32 位?
wait
和 wait_not
函数有 timeout 参数。但是,如果您需要具有潜在无限循环等待弹出窗口的精确侦听器,则好的方向是全局 Windows 挂钩(pyHook 可以侦听鼠标和键盘事件,但不能侦听对话框打开)。我将尝试找到可以检测新 windows 的原型。它使用 UI 自动化 API 事件处理程序...和...操作...它需要 IronPython。我仍然不知道如何使用标准 CPython.
中的 COM 接口设置 UI 自动化处理程序
编辑(2019 年 1 月):不久前在 pywinauto 中实现了新模块 win32hooks
。使用示例如下:examples/hook_and_listen.py.
有一个小的 javascript 实用程序可以在 Windows javascript 解释器上模拟这样的击键。
只需使用以下代码创建一个 js 文件:
var WshShell = WScript.CreateObject("WScript.Shell");
WshShell.SendKeys(WScript.Arguments(0));
然后在必要的超时后从 Matlab 调用它,如下所示:
system('c:\my\js\file\script.js {Enter}');
现在无法在这里测试,但我认为这应该可行...
如果您需要在允许完全 DOS 重定向的上下文中 运行 仅控制台程序,您可以创建一个名为 CR.txt 的文件,其中包含一个回车符 return并使用“<”符号将值通过管道传递到程序中。
这只有在您可以提供所有可以记录在文件中的键盘输入时才有效。如果输入必须根据响应而变化,它就会失败。
另一种方法是复制程序的输入(可能还有输出)流,然后通过管道将数据传入和传出程序。这更健壮,可以允许对数据进行动态响应,但也可能需要付出大量努力才能将机器人用户实施到应用程序中。
Rog-O-Matic 是一个大型应用程序的示例,该应用程序完全由监视屏幕输出并模拟键盘输入以玩早期(1980 年代)ASCII 图形冒险游戏的程序控制。
基于 GUI 的应用程序需要其他响应。
在 Matlab 中,我可以启动外部 .exe 文件,这些文件有时会弹出一个要求按下回车键的窗口。例如:
system('C:\Program Files (x86)\WinZip\WINZIP32.EXE')
将启动 Winzip,然后为了使用它,您需要按回车键通过 "buy now" 弹出 window。 现在我的问题不在于 winzip,我只是举个例子(反正我用的是 winrar :)。
在这种情况下,如何以编程方式在 Matlab 中按下回车键? (我用的是win 7)
可以使用事件侦听器来解决这个问题吗?
编辑:java.awt.Robot class 确实适用于资源管理器,但不适用于任何弹出 window 且需要按下确定按钮的软件。我不知道为什么它不起作用。我给出了 winzip 示例,因为我假设每个人都在他们的机器上安装了 winzip/winrar。我拥有的实际软件与问题不同且无关。
有一种方法可以使用来自 Matlab 的 Java,特别是 java.awt.Robot
class。参见 here。
显然有两种类型的程序,关于它们在使用 system('...')
从 Matlab 调用时的工作方式:
对于某些程序,Matlab 等待 直到程序在 运行 下一条语句之前完成。例如
WinRAR
(至少在我的 Windows 7 机器上)会发生这种情况。对于其他程序,这不会发生,Matlab 在外部程序启动后立即继续执行下一条语句。这种类型的一个例子是
explorer
(标准的 Windows 文件浏览器)。
现在,即使对于类型 1 程序,也可以 return 立即执行到 Matlab:只需在传递给 system
的字符串末尾添加 &
。这是standard in Linux Bash shell, and it also works in Windows, as discussed here。
因此,您将按如下方式进行:
robot = java.awt.Robot;
command = '"C:\Program Files (x86)\WinRAR\WinRAR"'; %// external program; full path
system([command ' &']); %// note: ' &' at the end
pause(5) %// allow some time for the external program to start
robot.keyPress (java.awt.event.KeyEvent.VK_ENTER); %// press "enter" key
robot.keyRelease (java.awt.event.KeyEvent.VK_ENTER); %// release "enter" key
如果您的应用程序仅在 Windows 平台上,您可以尝试使用 .net
个对象。
SendKeys
对象的 SendWait
方法允许将几乎任何键或键组合发送到具有焦点的应用程序,包括 "modifier" 键,如 Alt、Shift、Ctrl 等...
首先要做的是导入 .net
库,然后发送 ENTER 键的完整语法为:
NET.addAssembly('System.Windows.Forms');
System.Windows.Forms.SendKeys.SendWait('{ENTER}'); %// send the key "ENTER"
如果您只在完整语法确定后才这样做。如果您打算广泛使用该命令,您可以使用匿名辅助函数帮助自己。
记事本的一个小例子
%% // import the .NET assembly and define helper function
NET.addAssembly('System.Windows.Forms');
sendkey = @(strkey) System.Windows.Forms.SendKeys.SendWait(strkey) ;
%% // prepare a few things to send to the notepad
str1 = 'Hello World' ;
str2 = 'OMG ... my notepad is alive' ;
file2save = [pwd '\SelfSaveTest.txt'] ;
if exist(file2save,'file')==2 ; delete(file2save) ; end %// this is just in case you run the test multiple times.
%% // go for it
%// write a few things, save the file then close it.
system('notepad &') ; %// Start notepad, without matlab waiting for the return value
sendkey(str1) %// send a full string to the notepad
sendkey('{ENTER}'); %// send the {ENTER} key
sendkey(str2) %// send another full string to the notepad
sendkey('{! 3}'); %// note how you can REPEAT a key send instruction
sendkey('%(FA)'); %// Send key combination to open the "save as..." dialog
pause(1) %// little pause to make sure your hard drive is ready before continuing
sendkey(file2save); %// Send the name (full path) of the file to save to the dialog
sendkey('{ENTER}'); %// validate
pause(3) %// just wait a bit so you can see you file is now saved (check the titlebar of the notepad)
sendkey('%(FX)'); %// Bye bye ... close the Notepad
如 Microsoft 文档中所述,SendKeys
class 有时可能会出现一些计时问题,因此如果您想进行复杂的操作(例如 Tab 多次更改您实际想要按下的按钮),您可能必须在对 SendKeys
.
pause
不先尝试,但不要忘记您是在管理另一个进程,而它们之间没有任何同步,因此在正确安排之前可能需要反复试验所有时间,至少对于复杂的序列而言(简单的应该是直截了当的)。
以我上面的例子为例,我运行我所有的数据都来自一个外部硬盘驱动器,它具有ECO功能,可以让它进入待机状态,所以当我调用"save as..." 对话框,它需要一些时间才能显示,因为 HDD 必须唤醒。如果我不引入pause(1)
,有时文件路径会不完整(路径的第一部分在对话框获得焦点之前发送).
另外,执行外部程序时不要忘记&
字符。所有功劳都归功于 Luis Mendo 对它的强调。 (我往往会忘记它的重要性,因为我默认使用它。只有当我必须专门等待程序中的 return 值时,我才会省略它,否则我会 let it run on its own)
特殊字符有特殊代码。这里有一些:
Shift +
Control (Ctrl) ^
Alt %
Tab {TAB}
Backspace {BACKSPACE}, {BS}, or {BKSP}
Validation {ENTER} or ~ (a tilde)
Ins Or Insert {INSERT} or {INS}
Delete {DELETE} or {DEL}
Text Navigation {HOME} {END} {PGDN} {PGUP}
Arrow Keys {UP} {RIGHT} {DOWN} {LEFT}
Escape {ESC}
Function Keys {F1} ... {F16}
Print Screen {PRTSC}
Break {BREAK}
可以找到 Microsoft 的完整列表 here
Python 包 pywinauto 可以等待任何对话框并自动单击按钮。但它仅适用于本机和某些 .NET 应用程序。您可能在按下 WPF 按钮时遇到问题(也许 QT 按钮是可点击的 - 未选中),但在这种情况下,像 app.DialogTitle.wait('ready').set_focus(); app.DialogTitle.type_keys('{ENTER}')
这样的代码可能会有所帮助。您的情况非常简单,可能使用 pywinauto 的一些技巧就足够了。你的 "app with popup" 是 64 位还是 32 位?
wait
和 wait_not
函数有 timeout 参数。但是,如果您需要具有潜在无限循环等待弹出窗口的精确侦听器,则好的方向是全局 Windows 挂钩(pyHook 可以侦听鼠标和键盘事件,但不能侦听对话框打开)。我将尝试找到可以检测新 windows 的原型。它使用 UI 自动化 API 事件处理程序...和...操作...它需要 IronPython。我仍然不知道如何使用标准 CPython.
编辑(2019 年 1 月):不久前在 pywinauto 中实现了新模块 win32hooks
。使用示例如下:examples/hook_and_listen.py.
有一个小的 javascript 实用程序可以在 Windows javascript 解释器上模拟这样的击键。
只需使用以下代码创建一个 js 文件:
var WshShell = WScript.CreateObject("WScript.Shell");
WshShell.SendKeys(WScript.Arguments(0));
然后在必要的超时后从 Matlab 调用它,如下所示:
system('c:\my\js\file\script.js {Enter}');
现在无法在这里测试,但我认为这应该可行...
如果您需要在允许完全 DOS 重定向的上下文中 运行 仅控制台程序,您可以创建一个名为 CR.txt 的文件,其中包含一个回车符 return并使用“<”符号将值通过管道传递到程序中。
这只有在您可以提供所有可以记录在文件中的键盘输入时才有效。如果输入必须根据响应而变化,它就会失败。
另一种方法是复制程序的输入(可能还有输出)流,然后通过管道将数据传入和传出程序。这更健壮,可以允许对数据进行动态响应,但也可能需要付出大量努力才能将机器人用户实施到应用程序中。
Rog-O-Matic 是一个大型应用程序的示例,该应用程序完全由监视屏幕输出并模拟键盘输入以玩早期(1980 年代)ASCII 图形冒险游戏的程序控制。
基于 GUI 的应用程序需要其他响应。