在Matlab中,我可以启动外部.exe文件,有时会弹出一个需要按下回车键的文件。例如:
system('C:\Program Files (x86)\WinZip\WINZIP32.EXE')
将启动Winzip,然后为了使用它,您需要通过"立即购买"按Enter键弹出窗口。 现在我的问题不在于winzip,我只是作为一个例子(我还是使用winrar :)。
在这种情况下,如何以编程方式在Matlab中按Enter键? (我用win 7)
可以使用事件监听器来解决这个问题吗?
编辑:java.awt.Robot类确实适用于资源管理器,但不适用于任何具有需要按下的确定按钮的弹出窗口的软件。我不知道为什么它不起作用。我给了winzip的例子,因为我假设每个人都在他们的机器上安装了winzip / winrar。我拥有的实际软件与此问题不同且无关紧要。
答案 0 :(得分:26)
使用Matlab中的Java,特别是java.awt.Robot
类。请参阅here。
显然有两种类型的程序,关于它们在使用system('...')
从Matlab调用时的工作方式:
对于某些程序,Matlab 等待,直到程序完成后再运行下一个语句。例如,WinRAR
(至少在我的Windows 7机器中)会发生这种情况。
对于其他程序,这不会发生,并且Matlab 在外部程序启动后立即使用下一个语句进行。此类型的一个示例是explorer
(标准Windows文件资源管理器)。
现在,即使对于类型1程序,也可以立即将执行返回给Matlab:只需在传递给&
的字符串末尾添加system
。这是standard in Linux Bash shell,它也适用于Windows,如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
答案 1 :(得分:13)
如果您的应用程序仅在Windows平台上,则可以尝试使用.net
个对象。
SendKeys
对象的SendWait
方法允许将几乎任何键或组合键发送到具有焦点的应用程序,包括“修饰符”键,如 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
类有时会出现一些时序问题,因此如果您想进行复杂的操作(例如 Tab 多次更改您实际要按的按钮),您可能需要在对pause
的Matlab调用中引入SendKeys
。
首先尝试,但不要忘记你正在管理另一个进程而没有它们之间的任何同步,所以在你做对之前,所有这些都需要一些试验和错误,至少对于复杂的序列(简单)一个应该是直截了当的。)
在上面我的例子中,例如我从具有ECO功能的外部硬盘驱动器运行所有数据,将其置于待机状态,因此当我调用“另存为...”对话框时,需要时间它的显示因为硬盘必须唤醒。如果我没有引入pause(1)
,有时文件路径将是不完整的(路径的第一部分是在对话框有焦点之前发送的)。
此外,执行外部程序时不要忘记&
字符。所有这些都归功于Luis Mendo的突出显示。 (我倾向于忘记它的重要性,因为我默认使用它。如果我必须专门等待程序的返回值,我只会省略它,否则我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
答案 2 :(得分:3)
有一个小的javascript实用程序可以在Windows JavaScript解释器上模拟这样的击键。
只需使用以下代码创建一个js文件:
var WshShell = WScript.CreateObject("WScript.Shell");
WshShell.SendKeys(WScript.Arguments(0));
然后在必要的超时后从Matlab调用它:
system('c:\my\js\file\script.js {Enter}');
现在不能在这里测试,但我认为这应该有用......
答案 3 :(得分:3)
如果您需要在允许完全DOS重定向的上下文中运行仅限控制台的程序,您可以创建一个名为CR.txt的文件,例如包含回车符并使用'<&#39 ;将值输入程序的表示法。
这只有在你可以提供所有键盘输入的情况下才能记录在文件中。如果输入必须根据响应而变化,它就会失败。
另一种方法是复制程序的输入(和可能的输出)流,然后将数据导入和导出程序。这更加强大,可以允许对数据进行动态响应,但也可能需要大量工作才能将机器人用户实现到应用程序中。
Rog-O-Matic是一个大型应用程序的示例,它完全由一个程序控制,该程序监视屏幕输出并模拟键盘输入以播放早期(20世纪80年代)的ASCII图形冒险游戏。
基于GUI的应用程序将需要其他响应。
答案 4 :(得分:2)
Python包pywinauto可以自动等待任何对话框并单击按钮。但它只适用于本机和某些.NET应用程序。您可能在按下WPF按钮时遇到问题(可能QT按钮是可点击的 - 未选中),但在这种情况下,像app.DialogTitle.wait('ready').set_focus(); app.DialogTitle.type_keys('{ENTER}')
这样的代码可能有所帮助。你的情况很简单,pywinauto的一些技巧就足够了。你的“弹出窗口应用程序”是64位还是32位?
wait
和wait_not
个函数有 timeout 参数。但是,如果您需要具有可能无限循环等待弹出窗口的精确监听器,那么良好的方向是全局Windows挂钩(pyHook可以监听鼠标和keybd事件,但无法监听对话框打开)。我将尝试找到可以检测新窗口的原型。它使用UI Automation API事件处理程序...和...操作...它需要IronPython。我仍然不知道如何使用标准CPython的COM接口设置UI自动化处理程序。
EDIT(2019年1月):刚刚在pywinauto中实施了新模块win32hooks
。使用示例如下:examples/hook_and_listen.py。