Página 1 de 1

Ayuda con proceso araña de recorrido de BBDD

Publicado: 23 Ago 2011, 14:51
por raxor
Hola a todos, autoit me esta siendo de gran ayuda para automatizar procesos tontos que muchas veces tenemos que hacer los humanos. Quería hacer una consulta para ver cual es la mejor estrategia para un problema que tenemos.

Os cuento

En un formulario de consulta del aplicativo que utilizamos se trata de introducir un numero en un campo indice, mandar un "TAB" en el mismo y esperar a que se ejecute un proceso automático que hace unas verificaciones, pasar al numero siguiente y así hasta miles de números mas adelante.

He conseguido hacer un bucle que haga la tarea:

Código: Seleccionar todo

$numeroinicial = InputBox("Seguridad", "Numero de entrada de comienzo verificacion.", "")
$numerofinal = InputBox("Seguridad", "numero final.", "")

If Not WinActive("Consulta de documento","") Then WinActivate("Consulta de documento","")

For $i = $numeroinicial To $numerofinal
	Sleep(150)
	Send($i)
	Sleep(150)
	Send("{tab}")
	Sleep(150)
	If Not WinActive("Consulta de documento","") Then WinActivate("Consulta de documento","")
	WinWaitActive("Consulta de documento")
	Sleep(150)
	Send("{SHIFTDOWN}{TAB}")
	Send("{SHIFTUP}")
Next
Lo dejo ejecutado y mientras no toque el ratón o el teclado todo va bien ;)

El caso es que como tarda unos 30 segundos la verificación de cada numero quiero "instanciar" el proceso abriendo 2 veces la aplicación en pantalla y hacer un proceso que recorra hacia delante y otro hacia atrás.

Os enseño el código:

Código: Seleccionar todo

$numeroinicial = InputBox("Seguridad", "Numero de entrada de comienzo de verificacion.", "")
$numerofinal = InputBox("Seguridad", "numero final.", "")

;Cambio el titulo de cada una de las ventanas para poder trabajar con ellas

If Not WinActive("Consulta de documento","") Then WinActivate("Consulta de documento","")
$tmpTitle = WinGetTitle("Consulta de documento")
WinSetTitle($tmpTitle,"","UNO")

If Not WinActive("Consulta de documento","") Then WinActivate("Consulta de documento","")
$tmpTitle = WinGetTitle("Consulta de documento")
WinSetTitle($tmpTitle,"","DOS")

$i2 = $numerofinal

For $i = $numeroinicial To $numerofinal
	; Proceso creciente
	If Not WinActive("UNO","") Then WinActivate("UNO","")
	WinWaitActive("UNO")
	Sleep(1000)
	Send("{SHIFTDOWN}{TAB}")
	Send("{SHIFTUP}")
	Sleep(150)
	Send($i)
	Sleep(150)
	Send("{tab}")
	Sleep(150)
	; Proceso numero 2 decreciente
	If Not WinActive("DOS","") Then WinActivate("DOS","")
	Sleep(500)
	WinWaitActive("DOS")
	Sleep(1000)
	Send("{SHIFTDOWN}{TAB}")
	Send("{SHIFTUP}")
	Sleep(150)
	; Iterador que decrece
	$i2 = $i2-1
	Send($i2)
	Sleep(150)
	Send("{tab}")
	Sleep(150)
Next
El caso es que el script de autoit no espera en "WinWaitActive" (cuando es un unico proceso si que va bien), a pesar que aun no ha terminado la verificacion, autoit continua con las siguientes ordenes haciendo que todo se solape y mandando los comandos no sobre donde se requería.

¿Puedo preguntar con algún comando acerca del estado de la ventana ("UNO" o "DOS") o proceso y me responda si esta "busy" o si ya le puedo enchufar el siguiente número dado que en este caso winwaitactive no funciona?

¿Se os ocurre algo que pueda hacer?

Mil gracias

PD:No utilizo Controlsend porque la cabrona de mi aplicación cuando le da la gana cambia los números de instancia de los campos Edit (por ejemplo [CLASS:Edit; INSTANCE:60] y en un rato se redibuja el formulario y pasa al 61) no se porqué.

Saludos

Re: Ayuda con proceso araña de recorrido de BBDD

Publicado: 24 Ago 2011, 08:22
por Ximorro
Hum, curioso problema, puede que se esté volviendo loco con tanto cambio de ventana, quizás no da tiempo a cambiar el foco antes de hacer los Send.
Puedes probar a referenciar las ventanas por su handler, en vez de por título. Puede que igual tengas que cambiarles el título para poder distinguirlas inicialmente pero después si las referencias por handler no tiene que buscarlas de entre todas las ventanas de Windows, sino que va directamente a la que toca, con lo que será más rápido (quizás tienes un problema de timing, a ver si minimizándolo...)
Para el handler se utiliza WinGetHandle :

Código: Seleccionar todo

WinSetTitle("Consulta de documento","","UNO")
$hwndUNO = WinGetHandle("UNO")
WinSetTitle("Consulta de documento","","DOS")
$hwndDOS = WinGetHandle("DOS")
(creo que no hay que activarlas ni tomar el título completo con WinGetTitle como haces, así que se puede simplificar, pero no lo he comprobado)

Así luego accedes a ellas por manejador, en vez de título (se usan las mismas funciones), por ejemplo:
If Not WinActive($hwndUNO) Then WinActivate($hwndUNO)
WinWaitActive($hwndUNO)


Prueba también a incrementar los Sleep después de los WinWaitActive y también ANTES de WinActivate, esto último para asegurarse que le da tiempo a enviar las teclas antes de que le cambies la ventana, sería ese último Sleep(150), uno para cada ventana, prueba a darle más.

¿Por qué usas lo de {SHIFTDOWN} y {SHIFTUP}? ¿No funciona cambiar esos dos Send por un Send("+{TAB}")?

Una tontería, pero creo que el que va hacia atrás empieza en $numerofinal-1, pues decrementas $i2 antes de enviarlo, no sé si es esa la intención.

Y flipo, flipo mucho, con eso de que los controles cambian de nombre, eso es que los está creando cada vez nuevos, menudo gasto de recursos (espero que al menos esté eliminando los viejos y no poniendo los nuevos encima), igual tienen una buena razón pero a priori no da impresión de estar muy bien programado. ¿De dónde sale ese programa?

Re: Ayuda con proceso araña de recorrido de BBDD

Publicado: 24 Ago 2011, 09:01
por Ximorro
Por cierto, en el bucle, además de lo de empezar por $numerofinal-1, fíjate que los dos "procesos" hacen todo el recorrido, cuando ambos deberían parar a mitad.

He seguido dándole vueltas y hay algo que no entiendo, dices que tarda 30segs hacer el proceso para cada número, pero en el código eso no se refleja de ninguna manera. ¿Es que cuándo está trabajando no se deja activar y cuando la has podido activar es porque sabes que ya ha terminado?
Lo de mirar el estado pues puedes mirar eso, si está activa o no, pero si desactiva controles independientes quizás sea eso más fiable, ¡si es que puedes saber cómo se llaman o encontrarlos por texto, posición u otra manera!

Re: Ayuda con proceso araña de recorrido de BBDD

Publicado: 24 Ago 2011, 10:04
por raxor
Hola, antes de nada agradecerte tu tiempo para ayudarme, he probado a usar WinGetHandle siendo el resultado similar a lo anterior.

{SHIFTDOWN}{TAB}, es para volver al campo anterior (el campo numerico indice), {SHIFTUP} para soltar el shift (sino se queda pillado), en el codigo tengo otro SEND({TAB}).

Jeje ya sabia que en la primera iteracion hago $i2-1, como esto lo lanzo yo solo tengo que poner un numero mas del rango que quiero.

Para hacerlo mas robusto estoy cambiando la estrategia tengo un campo de tipo LABEL que da informacion del estado del proceso.

Voy a utilizarlo para que los procesos esperen a que cambie el valor.

EJ.

Código: Seleccionar todo

$valor1 = ControlGetText("DocUNO","","[CLASS:Edit; INSTANCE:2]")
While $valor1 = "Comprobando Solicitud..."
  sleep(1000)
  $valor1 = ControlGetText("DocUNO","","[CLASS:Edit; INSTANCE:2]")
Wend
Voy a replantearlo todo, dado que a veces un proceso corre mas que otro dado que algunos números ya están comprobados. voy a anidar 2 bucles en 1, termino cuando ambos procesos se encuentren. En un rato lo pruebo y cuelgo el código.

Seria algo así.

WHILE $i <= $i2
while campoLABELuno <> "Comprobando Solicitud..."
.......
send($i+{TAB})
$i=$i+1
wend

while campoLABELdos <> "Comprobando Solicitud..."
.......
send($i+{TAB})
$i2=$i2-1
wend
wend

Gracias

Re: Ayuda con proceso araña de recorrido de BBDD

Publicado: 24 Ago 2011, 11:10
por Ximorro
De nada hombre, para esto están los foros.

Es que lo que decía de Send("+{TAB}") es para eso. El "+" dentro de Send es un Shift, y cuando mande la pulsación ya suelta las dos teclas, debería funcionar igual este Send que los otros dos juntos.

Una cosa, lo de Clase+Instancia se usa tanto para identificar controles que AutoIt tiene una simplificación, poner "Edit2" es equivalente a "[CLASS:Edit; INSTANCE:2]". Eso sí, si realmente estás mirando un label, no un edit, entonces la clase debería ser Static, no Edit...

Hum, ese doble While no va a hacer lo que quieres porque primero haces todo el bucle del primero, y el segundo empezará a trabajar cuando el primero termine.

No va a ser tan fácil hacerlo trabajar concurrentemente, pues AutoIt no es multihilo, como mucho podrías hacer un lanzador que ejecute dos programas AutoIt, uno para cada ventana (los dos programas serían realmente el mismo programa ejecutado dos veces, pasando por ejemplo por la línea de comandos el rango de números que tienen que revisar, y de alguna manera la ventana que tienen que usar, a menos que la abran ellos mismos).

Otra cosa que se me ocurre es mirar las dos ventanas a la vez, y en cuando una deje de tener el "Comprobando Solicitud..." le mandas el próximo número a analizar. En plan pseudocódigo se me ocurre algo así como:

Código: Seleccionar todo

Mandar $numeroinicial a $ventanaUNO
Mandar $numeroinicial+1 a $ventanaDOS
$i = $numeroinicial+2
While $i <= $numerofinal
	$ventanaLibre = 0
	While $ventanaLibre = 0
		If $campoLABELuno <>  "Comprobando Solicitud..." Then
			$ventanaLibre = $ventanaUNO
		ElseIf $campoLABELdos <>  "Comprobando Solicitud..." Then
			$ventanaLibre = $ventanaDOS
		EndIf
	WEnd
	Mandar $i a $ventanaLibre
	$i += 1
WEnd
Editado: Perdón, no había visto bien tus bucles, me he liado con los While. O no, porque los WEnd particulares creo que deberían estar antes del Send. De todas maneras mientras una ventana está ocupada si te quedas esperando a que acabe, aunque la otra pueda estar libre. En un esquema como el que pongo creo que se consigue más concurrencia porque en cuando una ventana está libre la pones a trabajar (no digo que ese sea el código bueno, sino que esa es la idea)

Re: Ayuda con proceso araña de recorrido de BBDD

Publicado: 24 Ago 2011, 11:35
por raxor
Gracias otra vez, bueno es saber lo de (+{tab}), me estaba dando algún problema, me hacia cosas raras ;).

El enfoque de estar pendiente de las 2 ventanas lo voy a probar, es muy bueno y lógico por otra parte. Gracias por la inspiración :smt023

Código: Seleccionar todo

Mandar $numeroinicial a $ventanaUNO
Mandar $numeroinicial+1 a $ventanaDOS
$i = $numeroinicial+2
While $i <= $numerofinal
   $ventanaLibre = 0
   While $ventanaLibre = 0
      If $campoLABELuno <>  "Comprobando Solicitud..." Then
         $ventanaLibre = $ventanaUNO
      ElseIf $campoLABELdos <>  "Comprobando Solicitud..." Then
         $ventanaLibre = $ventanaDOS
      EndIf
   WEnd
   Mandar $i a $ventanaLibre
La verdad que ahora lo que estoy haciendo es lanzar el proceso individual en 2 equipos uno hacia delante otro hacia atrás como solución temporal, aparte he tenido que preveer algunos avisos del sistema con algunas entradas que me dejaban un msgbox a la espera de respuesta y paraban el proceso, los he salvado con esto:

Código: Seleccionar todo

if WinExists("Aviso") then
	If Not WinActive("Aviso","") Then WinActivate("Aviso","")
	WinWaitActive("Aviso")
	send("{ENTER}")
	sleep(500)
EndIf
if WinExists("Informacion") then
	If Not WinActive("Informacion","") Then WinActivate("Informacion","")
	WinWaitActive("Informacion")
	send("{ENTER}")
	sleep(500)
EndIf
if WinExists("Error") then
	If Not WinActive("Error","") Then WinActivate("Error","")
	WinWaitActive("Error")
	send("{ENTER}")
	sleep(500)
EndIf
Lo que se divierte uno en Agosto con autoit ;)

Gracias