presione programáticamente una tecla Intro después de iniciar el archivo.exe en Matlab
ui-automation (5)
Hay una manera de usar Java desde Matlab, específicamente la clase
java.awt.Robot
.
Mira
here
Al parecer, hay dos tipos de programas, en relación con la forma en que funcionan cuando se llama desde Matlab con el
system(''...'')
:
-
Para algunos programas, Matlab espera hasta que el programa haya terminado antes de ejecutar la siguiente declaración. Esto sucede, por ejemplo, con
WinRAR
(al menos en mi máquina con Windows 7). -
Para otros programas esto no sucede, y Matlab continúa con la siguiente declaración justo después de que se haya iniciado el programa externo. Un ejemplo de este tipo es el
explorer
(el explorador de archivos estándar de Windows).
Ahora, es posible devolver la ejecución a Matlab de inmediato, incluso para los programas de tipo 1: simplemente agregue
&
al final de la cadena pasada al
system
.
Esto es
estándar en Linux Bash Shell
, y también funciona en Windows, como se explica
here
.
Entonces, procedería de la siguiente manera:
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
En Matlab puedo iniciar archivos .exe externos que a veces tienen una ventana emergente que requiere presionar la tecla Intro. Por ejemplo:
system(''C:/Program Files (x86)/WinZip/WINZIP32.EXE'')
iniciará Winzip, y luego, para usarlo, debe pasar la ventana emergente "comprar ahora" presionando enter. Ahora mi problema no es con winzip, solo lo di como ejemplo (uso winrar de todos modos :).
¿Cómo puedo presionar programáticamente una tecla Intro en Matlab en tales casos? (Yo uso win 7)
¿Se puede usar un oyente de eventos para resolver eso?
EDITAR: La clase java.awt.Robot de hecho funciona en el explorador, pero no en ningún software que tenga una ventana emergente con un botón OK que deba presionarse. No sé por qué no funciona para eso. Di el ejemplo de winzip porque supongo que todos tienen winzip / winrar instalado en su máquina. El software real que tengo es diferente e irrelevante para la pregunta.
Hay una pequeña utilidad de JavaScript que simula pulsaciones de teclas como esta en el intérprete de JavaScript de Windows.
Simplemente cree un archivo js con el siguiente código:
var WshShell = WScript.CreateObject("WScript.Shell");
WshShell.SendKeys(WScript.Arguments(0));
luego llámalo desde Matlab después del tiempo de espera necesario como este:
system(''c:/my/js/file/script.js {Enter}'');
No puedo probar aquí ahora, pero creo que esto debería funcionar ...
Paquete Python
pywinauto
puede esperar cualquier diálogo y hacer clic en los botones automáticamente.
Pero es capaz solo para aplicaciones nativas y algunas aplicaciones .NET.
Es posible que tenga problemas al presionar el botón WPF (tal vez el botón QT sea clicable, no marcado), pero en ese caso, código como
app.DialogTitle.wait(''ready'').set_focus(); app.DialogTitle.type_keys(''{ENTER}'')
app.DialogTitle.wait(''ready'').set_focus(); app.DialogTitle.type_keys(''{ENTER}'')
puede ayudar.
Su caso es bastante simple y probablemente algunos trucos con pywinauto sean suficientes.
¿Su "aplicación con ventana emergente" es de 64 bits o de 32 bits?
wait_not
funciones
wait
y
wait_not
tienen un parámetro de
tiempo de espera
.
Pero si necesita un oyente preciso con bucle potencialmente infinito en espera de ventanas emergentes, una buena dirección son los ganchos globales de Windows (
pyHook
puede escuchar eventos de mouse y keybd, pero no puede escuchar la apertura del diálogo).
Trataré de encontrar mi prototipo que pueda detectar nuevas ventanas.
Utiliza controladores de eventos de API UI Automation ... y ... operaciones ... requiere IronPython.
Todavía no sé cómo configurar el controlador de automatización de la interfaz de usuario con la interfaz COM desde CPython estándar.
EDITAR (2019, enero): el nuevo módulo
win32hooks
se implementó en pywinauto hace un tiempo.
El ejemplo de uso está aquí:
examples/hook_and_listen.py
.
Si necesita ejecutar un programa solo de consola en un contexto que permita la redirección completa de DOS, puede crear un archivo llamado, por ejemplo, CR.txt que contenga un retorno de carro y usar la notación ''<'' para canalizar el valor en el programa.
Esto solo funciona si puede proporcionar toda la entrada del teclado que se puede grabar en el archivo. Falla lamentablemente si la entrada tiene que variar según las respuestas.
Una alternativa es duplicar la (s) secuencia (s) de entrada (y posiblemente de salida) para el programa y luego canalizar datos dentro y fuera del programa. Esto es más robusto y puede permitir respuestas dinámicas a los datos, pero también requerirá un esfuerzo considerable para implementar un usuario de robot en la aplicación.
Rog-O-Matic es un ejemplo de una gran aplicación completamente controlada por un programa que monitorea la salida de pantalla y simula la entrada del teclado para jugar un juego de aventura gráfica ASCII de principios de la década de 1980.
Las otras respuestas serán necesarias para las aplicaciones basadas en GUI.
Si sus aplicaciones solo están en la plataforma Windows, puede intentar usar objetos
.net
.
El método
SendWait
de los objetos
SendKeys
permite enviar prácticamente cualquier tecla o combinación de teclas a la aplicación que tiene el foco, incluidas las teclas "modificadoras" como
Alt
,
Shift
,
Ctrl
, etc.
Lo primero que debe hacer es importar la biblioteca
.net
, luego la sintaxis completa para enviar la clave
ENTER
sería:
NET.addAssembly(''System.Windows.Forms'');
System.Windows.Forms.SendKeys.SendWait(''{ENTER}''); %// send the key "ENTER"
Si solo lo hace una vez, la sintaxis completa está bien. Si planea hacer un uso extensivo del comando, puede ayudarse con una función auxiliar anónima.
Un pequeño ejemplo con el bloc de notas
%% // 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
Como se explica en la documentación de
Microsoft
, la clase
SendKeys
puede tener algunos problemas de sincronización a veces, por lo que si desea realizar manipulaciones complejas (como
Tab
varias veces para cambiar el botón que realmente desea presionar), es posible que deba introducir una
pause
en sus llamadas de Matlab a
SendKeys
.
Intente sin primero, pero no olvide que está administrando un proceso desde otro sin ninguna sincronización entre ellos, por lo tanto, cronometrar todo lo que puede requerir un poco de prueba y error antes de hacerlo bien, al menos para secuencias complejas (una simple debería ser sencillo).
En mi caso anterior, por ejemplo, estoy ejecutando todos mis datos desde un disco duro externo con una función ECO que lo pone en espera, por lo que cuando llamé al cuadro de diálogo "Guardar como ...", toma tiempo para que se muestre porque el HDD tiene que despertarse.
Si no introduje la
pause(1)
, a veces la ruta del archivo estaría incompleta (la primera parte de la ruta se envió antes de que el diálogo tuviera el foco)
.
Además, no olvide el carácter
&
cuando ejecute el programa externo.
Todo el crédito a Luis Mendo por destacarlo.
(Tiendo a olvidar lo importante que es porque lo uso de forma predeterminada. Solo lo omito si tengo que esperar específicamente un valor de retorno del programa, de lo contrario lo
dejo correr solo
)
Los caracteres especiales tienen un código especial. Aquí hay algunos:
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}
La lista completa de Microsoft se puede encontrar here