在Matlab中启动.exe文件后以编程方式按回车键

时间:2015-01-13 23:16:35

标签: matlab ui-automation

在Matlab中,我可以启动外部.exe文件,有时会弹出一个需要按下回车键的文件。例如:

system('C:\Program Files (x86)\WinZip\WINZIP32.EXE')

将启动Winzip,然后为了使用它,您需要通过"立即购买"按Enter键弹出窗口。 现在我的问题不在于winzip,我只是作为一个例子(我还是使用winrar :)。

在这种情况下,如何以编程方式在Matlab中按Enter键? (我用win 7)

可以使用事件监听器来解决这个问题吗?

编辑:java.awt.Robot类确实适用于资源管理器,但不适用于任何具有需要按下的确定按钮的弹出窗口的软件。我不知道为什么它不起作用。我给了winzip的例子,因为我假设每个人都在他们的机器上安装了winzip / winrar。我拥有的实际软件与此问题不同且无关紧要。

5 个答案:

答案 0 :(得分:26)

使用Matlab中的Java,特别是java.awt.Robot类。请参阅here

显然有两种类型的程序,关于它们在使用system('...')从Matlab调用时的工作方式:

  1. 对于某些程序,Matlab 等待,直到程序完成后再运行下一个语句。例如,WinRAR(至少在我的Windows 7机器中)会发生这种情况。

  2. 对于其他程序,这不会发生,并且Matlab 在外部程序启动后立即使用下一个语句进行。此类型的一个示例是explorer(标准Windows文件资源管理器)。

  3. 现在,即使对于类型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位?

waitwait_not个函数有 timeout 参数。但是,如果您需要具有可能无限循环等待弹出窗口的精确监听器,那么良好的方向是全局Windows挂钩(pyHook可以监听鼠标和keybd事件,但无法监听对话框打开)。我将尝试找到可以检测新窗口的原型。它使用UI Automation API事件处理程序...和...操作...它需要IronPython。我仍然不知道如何使用标准CPython的COM接口设置UI自动化处理程序。


EDIT(2019年1月):刚刚在pywinauto中实施了新模块win32hooks。使用示例如下:examples/hook_and_listen.py