Deteccion STDOUT
Deteccion STDOUT
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
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
- ............................................
......................................
Re: Deteccion STDOUT
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...
De todas formas voy a ver si puedo darle vueltas al asunto e ir viendo...
Re: Deteccion STDOUT
puedes comentar que herramienta es para tener mas noción de lo que quieres hacer?
- ............................................
......................................
Re: Deteccion STDOUT
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.
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...
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.
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
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
saludos tambien podrias analizar bien el commandline y hacer algo como quieres.
saludos
- ............................................
......................................
Re: Deteccion STDOUT
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:
Llego a casa y lo pruebo mejor a ver cómo va y comento que fue lo que pasó...
Gracias Dany por tus respuestas!!!!
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)
Gracias Dany por tus respuestas!!!!
Re: Deteccion STDOUT
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.
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!!
Ni bien termino de apretar el botón "enviar", veo en el código que el "&" de "$dos_output &=…" me saludaba.
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
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:
De esta forma, consigo el resultado del comando tanto en consola como en el MsgBox.
Pero algo no acaba de funcioar del todo porque si el comando no es interno de DOS como por ejemplo el CHKDSK
o incluso
No obtengo resultado ninguno
¿alguna sugerencia de por que sucede esto?
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)
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)
Código: Seleccionar todo
Local $cmd = Run("C:\Windows\System32\CHKDSK.exe", "", @SW_HIDE, $STDOUT_CHILD)
No obtengo resultado ninguno
¿alguna sugerencia de por que sucede esto?
Re: Deteccion STDOUT
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:
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
Espero se entienda saludos!
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
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
Espero se entienda saludos!
Re: Deteccion STDOUT
@PDF el error creo que es por esta relación:
Saludos
Código: Seleccionar todo
$dllcall=DllCall("msvcrt.dll","int:cdecl","printf","str","%s","str","Hola" & @CR)
Saludos
- ............................................
......................................
Re: Deteccion STDOUT
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
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é
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!
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
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
Dany, perdón por la ignorancia, pero ¿qué es lo que haría esa llamada?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