Página 1 de 1

Deteccion STDOUT

Publicado: 12 May 2014, 15:19
por Marcelo
Hola, ante todo, no sé si estará bien elegido el título del post pero no sabía cómo llamarlo.
Bueno, la pregunta es la siguiente: Tengo un programa de línea de comando al que deseo hacerle una interfaz (GUI), este va informando el proceso de trabajo mediante salida STDOUT.
¿Existe alguna manera, función, UDF, o como sea de ir leyendo estas salidas en tiempo real para poder ir informándolas tal cual aparecen en la GUI o necesariamente hay que esperar a que termine para poder obtenerlas?
Sé que se podría crear una salida a un archivo, pero estoy en la misma ya que el archivo no puede ser leido hasta que esté cerrado y el proceso puede tardar vaaaarios minutos y nunca se sabría si el programa sigue corriendo o se ha colgado...
Desde ya muchísimas gracias

Marcelo

Re: Deteccion STDOUT

Publicado: 12 May 2014, 22:25
por Dany

Re: Deteccion STDOUT

Publicado: 12 May 2014, 22:41
por Marcelo
Muchísimas gracias por la respuesta, perdón si hay algo que no entiendo. Pero para leer los valores mediante esa función no tengo que esperar que el proceso haya terminado?
De todas formas voy a ver si puedo darle vueltas al asunto e ir viendo...

Re: Deteccion STDOUT

Publicado: 12 May 2014, 22:47
por Dany
puedes comentar que herramienta es para tener mas noción de lo que quieres hacer?

Re: Deteccion STDOUT

Publicado: 12 May 2014, 22:58
por Marcelo
Perdón, por obviar eso. Son un par de cosas las que quiero hacer, pero entre ellas intentaría usar algún conversor de formatos de videos como el FFMPEG y me gustaría hacer algo parecido para el "clamscan.exe" del antivirus "clamav"
Sé que me dirán que existen ya cosas hechas para esto, pero quiero integrarlas a aplicaciones que ya tengo hechas y, por sobre todo, a título de "desafío personal", ya que sólo soy un programador hobbista. :smt002
Básicamente quiero ejecutar el "archivo.exe" con sus parámetros e ir informando de manera prolija en mi GUI cada una de las salidas que este vaya entregando, y así también poder informar el porcentaje de trabajo realizado...

Re: Deteccion STDOUT

Publicado: 12 May 2014, 23:03
por Dany
mmm pues por ejemplo para el antivirus. supongamos que quieres hacer un scanner de antivirus con el commandline. la verdad no seria muy seguro ir leyendo la consola e ir parseando las cadenas. seria mejor escrbir en un txt. y luego parsear todo.


saludos tambien podrias analizar bien el commandline y hacer algo como quieres.



saludos

Re: Deteccion STDOUT

Publicado: 12 May 2014, 23:35
por Marcelo
Ojo, que mi intención no es hacer el antivirus, sólo informar mediante un GUI.
No tengo acá el ejecutable porque estoy en una máquina linux, pero por lo que estuve viendo ayer puedo hacerte un ejemplo de memoria nomás.
La ejecución sería algo como "clamscan -r c:" y la salida algo como esto:

Cargando la base de datos /
Cargando la base de datos -
Cargando la base de datos \
Cargando la base de datos -
Cargando la base de datos /
Cargando la base de datos -
Cargando la base de datos \
Cargando la base de datos Listo
Analizando C:\Autoexec.bat: OK
Analizando C:\Archivo2.ext: OK
Analizando C:\Archivo3.ext: Nombre del virus encontrado FOUND
Analizando C:\Archivo4.ext: OK

y así hasta terminar.
Mi idea es poder poder asignar cada uno de esos "renglones" a un label dentro de la ventanita del GUI y, como ideal, por cada una de las que contengan FOUND hacer un parse y agregarlos a una lista con "nombre de archivo" e "infección".
Todo eso tengo en mente como hacerlo, lo único que no se si es posible es ir tomando cada una de las salidas para ir informándolas, ya que el proceso puede durar entre minutos y horas.

Agrego para no crear una nueva respuesta:

Bueno, estuve intentando algunas cosas y al parecer funciona, no pude aguantarme y lo estoy probando en linux con Wine así que la respuesta no es la óptima pero al menos parece que puedo ir tirando las salidas a la consola, será cosa de llegar a casa y probar algo más elaboradito en windows y ver qué pasa.
El código que estoy probando es el siguiente:

Código: Seleccionar todo

#include <Constants.au3>
Local $dos_output = "" 
Local $cmd = Run(@ScriptDir & "\clamscan.exe -r c:","",@SW_HIDE,$STDOUT_CHILD)
While Not @error 
    $dos_output &= StdoutRead($cmd) 
	ConsoleWrite($dos_output & @CRLF)
WEnd
MsgBox(0, "Terminado", $dos_output)
Llego a casa y lo pruebo mejor a ver cómo va y comento que fue lo que pasó... :smt002
Gracias Dany por tus respuestas!!!!

Re: Deteccion STDOUT

Publicado: 13 May 2014, 15:23
por Marcelo
Bueno, anoche después de renegar un rato y echarle la culpa a que el "peek" no funcionaba como debería hacerlo, puse una respuesta a este post preguntando si alguien tenía alguna idea de por qué no podía obtener las salidas una a una sino toda la acumulación de las mismas.
Ni bien termino de apretar el botón "enviar", veo en el código que el "&" de "$dos_output &=…" me saludaba. :smt002
Automáticamente dije NOOOOO, lo corregí, y puedo afirmar que funciona perfectamente para lo que necesito.
Cosas del "copiar y pegar" sin revisar en detalle.
Perdón, mala mía. ;)
Y gracias!!

Re: Deteccion STDOUT

Publicado: 14 May 2014, 10:03
por juantxo
Me ha parecido un tema muy interesante, por lo que me he puesto ha hacer alguna prueba en base a tu Script, modificando el Comando que enviaba, pero no obtenia resultados en pantalla.

Si que mostraba informacion si añadia el parametro peek a la funcion StdoutRead ($cmd,True) pero concatenaba las lineas hasta que daba un error de memoria.

Creo que la culpa es del comando While que no termina nunca una vez que entra en el bucle, asi que he modificado el código como sigue:

Código: Seleccionar todo

#include <Constants.au3>
Local $dos_output = "", $txt_res = ""
Local $cmd = Run(@ComSpec & " /c " & "dir c:\ ", "", @SW_HIDE, $STDOUT_CHILD)

While ProcessExists($cmd)
	$dos_output = StdoutRead($cmd)
	If $dos_output <> "" Then
		ConsoleWrite($dos_output & @CRLF)
		$txt_res &= $dos_output
	EndIf

WEnd
MsgBox(0, "Terminado", $txt_res)
De esta forma, consigo el resultado del comando tanto en consola como en el MsgBox. :smt043 :smt036 :smt043

Pero algo no acaba de funcioar del todo porque si el comando no es interno de DOS como por ejemplo el CHKDSK

Código: Seleccionar todo

Local $cmd = Run(@ComSpec & " /c " & "CHKDSK c: ", "", @SW_HIDE, $STDOUT_CHILD)
o incluso

Código: Seleccionar todo

Local $cmd = Run("C:\Windows\System32\CHKDSK.exe", "", @SW_HIDE, $STDOUT_CHILD)

No obtengo resultado ninguno :smt018 :smt017 :smt018

¿alguna sugerencia de por que sucede esto?

:smt010 :smt010 :smt010

Re: Deteccion STDOUT

Publicado: 15 May 2014, 15:50
por PDF
Sin dudas es un tema interesante, por mi parte me puse a hacer mi propio ejemplo, utilizé el comando interno de windows CHKDSK y es el siguiente:

Código: Seleccionar todo

#include <GUIConstantsEx.au3>
#include <StaticConstants.au3>
#include <WindowsConstants.au3>

$Form1 = GUICreate("Stdout Read", 464, 345, 223, 146)
$Label1 = GUICtrlCreateLabel("Verificando Unidad de disco:", 40, 16, 140, 17)
$Label2 = GUICtrlCreateEdit("", 40, 48, 380, 220)
GUICtrlSetData(-1, "")
$Progress1 = GUICtrlCreateProgress(40, 288, 382, 17)
$Input1 = GUICtrlCreateInput("H:", 200, 16, 121, 21)
$Button1 = GUICtrlCreateButton("Verificar", 336, 16, 75, 25)
$Label3 = GUICtrlCreateLabel("Listo", 40, 312, 388, 14)
GUISetState(@SW_SHOW)

While 1
	$nMsg = GUIGetMsg()
	Switch $nMsg
		Case $GUI_EVENT_CLOSE
			Exit
		Case $Button1
			$Volume = GUICtrlRead($Input1)
			$Pro = Run(@ComSpec & " /c Chkdsk " & $Volume, "", @SW_HIDE, 2) ; Ejecuutamos la consola en modo oculto con el parametro $STDOUT_CHILD
			While ProcessExists($Pro) ; Verfica si existe el proceso
				$read = StdoutRead($Pro) ; Lee la salida STDOUT
				If StringInStr($read, "por ciento") Then
					GUICtrlSetData($Progress1, Number($read)) ; Utiliza el porcentaje que envia el Chkdsk para el progressbar
				Else
					GUICtrlSetData($Label2, $read, 1) ; Muestra el resultado en el edit
				EndIf
				GUICtrlSetData($Label3, $read)
			WEnd
			GUICtrlSetData($Progress1, 100) ; Generalmente queda en 99 por ciento completado, lo llenamos.
			GUICtrlSetData($Label3, "Listo")
	EndSwitch
WEnd
El resultado es mostrado en un edit y el progreso de la operación en un progressbar, sin esperar que se cierre el proceso de la consola, es decir, el resultado es mostrado en tiempo real..

Pero hay algo... al ejecutarse desde el SciTe, la consola se cierra inmediatamente por lo que se debe ejecutar directamente el archivo desde el menu contextual, a que se debera esto :smt017
Espero se entienda saludos!

Re: Deteccion STDOUT

Publicado: 15 May 2014, 16:48
por Dany
@PDF el error creo que es por esta relación:

Código: Seleccionar todo

$dllcall=DllCall("msvcrt.dll","int:cdecl","printf","str","%s","str","Hola" & @CR)

Saludos :smt027

Re: Deteccion STDOUT

Publicado: 15 May 2014, 17:20
por PDF
Mmm veo que el SciTE recoge también lo que envia la consola por medio de Sdout y tal vez se deba a esto.. Lo que decia es que, si ejecuto el script en el scite no hay resultados, pero si lo hago directamente funciona bien...

Re: Deteccion STDOUT

Publicado: 15 May 2014, 21:16
por Marcelo
Efectivamente Juantxo con StdoutRead($cmd,True) lee los valores de la salida pero no limpia el buffer, de esa forma siempre se obtiene la concatenación.
Para lo que buscamos, necesitamos ponerlo en "False" (valor por default)
Con respecto a la "NO información", a mi me pasaba, y era porque el bucle iba más rápido de lo que el programa generaba salidas, por decirlo de alguna manera.
Eso lo solucioné haciendo una comparación e informando únicamente si tenia qué

Código: Seleccionar todo

$out = StdoutRead($cmd,True)
If $out then
     guictrlsetdata($label,$out)
endif
Una vez capturados los datos hago las operaciones que quiero sobre el "string" e informo como quiero, nombre, porcentaje realizado, actualizo una lista cuando hay un objeto infectado, etc.
Para terminar, lo que hice fue lo mismo que en los ejemplos anteriores y es hacer el while verificando si el proceso seguía activo.
Hay casos en que determinados programas generan salidas en STDERR a la vez que STDOUT, para informar errores, eso también puede capturarse y no está de más.
Realmente muy entretenido!

Re: Deteccion STDOUT

Publicado: 15 May 2014, 21:21
por Marcelo
Dany escribió:@PDF el error creo que es por esta relación:

Código: Seleccionar todo

$dllcall=DllCall("msvcrt.dll","int:cdecl","printf","str","%s","str","Hola" & @CR)

Saludos :smt027
Dany, perdón por la ignorancia, pero ¿qué es lo que haría esa llamada?