Подтвердить что ты не робот

Программно нажмите клавишу ввода после запуска .exe файла в Matlab

В Matlab я могу запускать внешние .exe файлы, которые когда-то имеют всплывающие окна, для которых требуется клавиша ввода. Например:

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

запустит Winzip, а затем, чтобы использовать его, вам нужно пройти всплывающее окно "buy now", нажав enter. Теперь моя проблема не в winzip, я только привел ее в качестве примера (я все равно использую winrar:).

Как я могу программно нажать клавишу ввода в Matlab в таких случаях? (Я использую win 7)

Может ли прослушиватель событий использоваться для решения этой проблемы?

EDIT: класс java.awt.Robot действительно работает на проводнике, но не на любом программном обеспечении, у которого есть всплывающее окно с кнопкой OK, которую нужно нажать. Я не знаю, почему это не сработает. Я привел пример winzip, потому что я предполагаю, что у каждого установлен winzip/winrar на их машине. Фактическое программное обеспечение, которое у меня есть, отличается и не имеет отношения к вопросу.

4b9b3361

Ответ 1

Существует способ использования Java из Matlab, в частности класса java.awt.Robot. См. здесь.

По-видимому, существуют два типа программ, касающихся того, как они работают при вызове из Matlab с помощью system('...'):

  • Для некоторых программ Matlab ждет, пока программа не закончит работу перед запуском следующего оператора. Это происходит, например, с помощью WinRAR (по крайней мере, на моей машине с Windows 7).

  • Для других программ этого не происходит, и Matlab переходит со следующей операцией сразу после запуска внешней программы. Примером такого типа является explorer (стандартный проводник файлов Windows).

Теперь можно сразу же выполнить выполнение в Matlab даже для программ типа 1: просто добавьте & в конец строки, переданной в system. Это стандарт в Linux Bash shell, и он также работает в Windows, как обсуждалось здесь.

Итак, вы должны действовать следующим образом:

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

Ответ 2

Если ваши приложения находятся только на платформе Windows, вы можете попробовать использовать объекты .net.

Метод SendWait объектов SendKeys позволяет отправлять практически любую клавишу или комбинацию клавиш в приложение, которое имеет фокус, включая клавиши "модификатора", такие как 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), иногда путь к файлу был бы незавершенным (первая часть пути была отправлена ​​до того, как диалог имел фокус).


Кроме того, не забудьте символ & при выполнении внешней программы. Все заслуги Луиса Мендо за его выделение. (Я, как правило, забываю, насколько это важно, потому что я использую его по умолчанию. Я только опускаю его, если мне нужно специально ожидать возврата от программы, иначе я пусть он работает его собственный)


Специальные символы имеют специальный код. Вот несколько:

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 можно найти здесь

Ответ 3

Существует небольшая утилита javascript, которая имитирует нажатия клавиш, подобных этому в интерпретаторе javascript Windows.

Просто создайте файл js со следующим кодом:

var WshShell = WScript.CreateObject("WScript.Shell");
WshShell.SendKeys(WScript.Arguments(0));

затем вызовите его из Matlab после необходимого таймаута следующим образом:

system('c:\my\js\file\script.js {Enter}');

Не могу проверить здесь сейчас, но я думаю, что это должно сработать...

Ответ 4

Если вам нужно запустить консольную программу в контексте, который допускает полное перенаправление DOS, вы можете создать файл, скажем, CR.txt, содержащий возврат каретки, и использовать нотацию "<" для передачи значения в программу.

Это работает только в том случае, если вы можете указать, что весь ввод с клавиатуры может быть записан в файл. Это терпит неудачу, если входные данные должны варьироваться в зависимости от ответов.

Альтернативой является дублирование входного (и, возможно, выходного) потока (ов) для программы, а затем передача данных в программу и из нее. Это более надежно и может позволить динамические ответы на данные, но также, вероятно, потребует значительных усилий для внедрения пользователя робота в приложение.

Rog-O-Matic - это пример большого приложения, полностью контролируемого программой, которая контролирует вывод на экран и имитирует ввод с клавиатуры, чтобы играть в раннюю (1980-е) графическую приключенческую игру ASCII.

Другие ответы будут необходимы для приложений на основе графического интерфейса.

Ответ 5

Пакет Python pywinauto может ждать любого диалога и автоматически нажимать кнопки. Но он способен только для нативных и некоторых приложений .NET. У вас могут быть проблемы с нажатием кнопки WPF (возможно, кнопка QT щелкается - не проверяется), но в этом случае код, такой как app.DialogTitle.wait('ready').set_focus(); app.DialogTitle.type_keys('{ENTER}') app.DialogTitle.wait('ready').set_focus(); app.DialogTitle.type_keys('{ENTER}') может помочь. Ваш случай довольно прост, и, вероятно, некоторых трюков с Pywinauto достаточно. Ваше приложение с всплывающим окном 64-битное или 32-битное?

wait_not wait и wait_not имеют параметр timeout. Но если вам нужен точно прослушиватель с потенциально бесконечным циклом, ожидающим всплывающие окна, хорошее направление - это глобальные перехватчики Windows (pyHook может прослушивать события мыши и keybd, но не может прослушивать открытие диалога). Я постараюсь найти свой прототип, который может обнаружить новые окна. Он использует обработчики событий API пользовательского интерфейса... и... опс... он требует IronPython. Я до сих пор не знаю, как установить обработчик автоматизации пользовательского интерфейса с интерфейсом COM из стандартного CPython.


РЕДАКТИРОВАТЬ (2019, январь): новый модуль win32hooks был реализован в pywinauto некоторое время назад. Пример использования здесь: examples/hook_and_listen.py.