Página 1 de 1

Eliminarse a si mismo. Se puede optimizar?

Publicado: 23 Sep 2010, 05:04
por dertin
Hola, como estan.. :)

Les quiero enseñar mi codigo, parece inutil, pero lo quiero implementar en otro Script, en una funcion de desintalacion, dentro del mismo programa que simpre esta en modo de ejecucion, es algo complejo de explicar. Les paso a contar sobre el codigo que comparto al final del Post. :smt002

Su función es eliminarse a si mismo("Script compilado en .EXE"), lanza un código batch que como ven, hace una pausa o sleep (causada por "ping -n 2 -w 1 127.0.0.1" equivale a 1seg, esta dentro de un FOR y este comando se repite 5 veces en mi ejemplo, resultando 5 seg) que son suficientes para luego de haber terminado la pausa, nuestro programa de AutoIT ya este cerrado; el batch que aun corre luego de la pausa lanza el comando
DEL MIPROGRAMA.EXE (nombre de nuestro Script compilado de ejemplo), este se borra ya que no esta en ejecución. y por ultimo el batch con el comando DEL temp.bat elimina el mismo archivo Script batch temporal ejecutado en memoria que anteriormente lanzo nuestra aplicacion de AutoIT segundo antes de cerrarse.

El código NO esta optimizado, por ahí se crea un archivo temp.bat (tal vez no sea necesario) usando Run(@ComSpec & ' /c FOR........ ' ,' ',@SW_HIDE) no me resulto, tal vez cometí algún error; o algo similar a eso.. pienso yo.. No se si hay otra forma de hacer esto que hice, me gustaría saberlo. Si pueden aconsejarme alguna forma de mejorar el código para que piense en algún cambio gracias.

Aquí les dejo el código, espero que resulte de este código otro mejorado en conjunto mutuo :smt047

Código: Seleccionar todo

#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_outfile=MIPROGRAMA.exe
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****

$file = FileOpen("temp.bat",1)

	If $file = -1 Then
		MsgBox(0,"Error","Error")
	EndIf

FileWrite($file, "@ECHO OFF" & @CRLF & "FOR /l %%a IN (5,-1,1) do (ECHO 1 >NUL %%as&ping -n 2 -w 1 127.0.0.1>NUL)" & @CRLF & "DEL MIPROGRAMA.EXE" & @CRLF & "DEL temp.bat")
FileClose($file)

Run('temp.bat','',@SW_HIDE)

Exit
Saludos, dertin

Re: Eliminarse a si mismo. Se puede optimizar?

Publicado: 23 Sep 2010, 08:20
por Chefito
Mmmmmm....hace poco puse un tema en que participamos Ximorro y yo con código. El tema se titulaba "Como escribir información dentro del exe?". Era algo más complicado que solo borrarlo, pero también nos encontrábamos con el mismo problema que tú, ya que no se puede cambiar un archivo exe en ejecución.
La base de tú método es practicamente igual al código de Ximorro. Por supuesto el hizo algunas mejoras :smt002 .
Tienes varias formas, desde mandar en una sola línea de comandos, sin generar un archivo bat, las órdenes (con sus limitaciones que esto supone claro), hasta generar un archivo bat que espera justamente a que se termine el proceso de nuestro exe para poder borrarlo.
Yo, para hacer lo anterior utilicé un archivo vbs, aunque en el caso de solo borrar el archivo no hace mucha falta. Con un bat sobra.

http://www.emesn.com/autoitforum/viewto ... f=3&t=2254

Saludos.

Re: Eliminarse a si mismo. Se puede optimizar?

Publicado: 23 Sep 2010, 08:53
por Ximorro
Efectivamente, allí modificábamos el exe original, que es algo más complicado que borrarlo, así que tu problema es más sencillo.

Te recomiendo usar el método de lanzar una consola al vuelo (con @ComSpec & ' /c ' & $comandoborrador tal como intentabas, el problema es que asó no hemos encontrado manera de ejecutar códigos de varias líneas :smt010 ), así no se crea archivo BAT y en tu caso es más que suficiente.
El método de Chefito es muy versátil y a tener en cuenta para hacer cosas más complicadas, pero en este caso no hace falta generar archivos auxiliares, ya sean BAT o VBS.

Por cierto, el parámetro -w de ping está en milisegundos, no segundos, así que deberías poner -w 1000, pero eso NO ES el tiempo entre dos pings, sino el que espera uno que falle hasta hacer timeout. Si no falla, NO esperará ese tiempo, y de hecho 127.0.0.1 contestará enseguida así que no estás controlando bien el tiempo pues no se espera el segundo que quieres, sino que finaliza en cuando 127.0.0.1 responde, que es en menos de un milisegundo.
No hace falta que uses ese parámetro, por defecto entre ping y ping hay siempre un segundo (lástima no poder controlar ese tiempo), para hacerlo sin BAT simplemente puedes esperar un par de segundos, (haciendo TRES ping con el parámetro -n 3, eso tendrá DOS pausas de un segundo) y luego borras.

Para hacer que se borre el EXE exactamente cuando esté libre para escritura puedes controlarlo con tasklist, qprocess, o directamente haciendo DEL hasta que deje de dar error (todas esas cosas se comentan en el enlace que te ha puesto Chefito, aunque allí en vez de DEL es MOVE, porque en vez de borrarlo lo machacábamos con una versión modificada)
De todas maneras estas cosas ya requieren bucles (varias líneas), con lo que es necesario un archivo BAT, que por supuesto también hay que borrar.

Re: Eliminarse a si mismo. Se puede optimizar?

Publicado: 25 Sep 2010, 22:19
por dertin
Gracias Ximorro por la ayuda con los parametros del comando ping, intente formas de hacerlo lanzando una consola al vuelo como tu dices, pero no encontre manera. Se que se puede ejecutar un FOR si no me equivoco en una linea sola de comando y talvez utilizando & para anidar varios comandos.
Pero en lo que es programacion Batch se solo lo basico.

Miren eh quitado el For con la pausa y lo eh hecho usando un IF y un GOTO de esta forma es mas rapido y mas confiable pero aun creando un Script Batch;
Por ahi Ximorro lo comentaba en el post de Chefito usando MOVE ... || GOTO ... algo similar hice.

Código: Seleccionar todo

#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_outfile=MIPROGRAMA.exe
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****

Func _MeBorro()

Local $tempFile = "temp.bat"
Local $dirProgram = "MIPROGRAMA.exe"

$file = FileOpen($tempFile,1)

	If $file = -1 Then
		MsgBox(0,"Error","Error al crear " & $tempFile)
	EndIf

FileWrite($file, "@ECHO OFF" & @CRLF & "IF EXIST " & $dirProgram & " GOTO Borrar" & @CRLF & ":Borrar" & @CRLF & "DEL " & $dirProgram & @CRLF & "IF EXIST " & $dirProgram & " GOTO Borrar" & @CRLF & "DEL " & $tempFile)

FileClose($file)

Run($tempFile,'',@SW_HIDE)

Exit

EndFunc

_MeBorro()

Creo que esta es la forma más optima de hacer lo que quiero.
Gracias por tu otro Post Chefito que mire!

Re: Eliminarse a si mismo. Se puede optimizar?

Publicado: 26 Sep 2010, 13:15
por Chefito
Hombre, puestos a optimizar........

Código: Seleccionar todo

FileWrite($file, ":Borrar" & @CRLF & "DEL " & $dirProgram & @CRLF & "IF EXIST " & $dirProgram & " GOTO Borrar" & @CRLF & "DEL " & $tempFile)
Saludos.

Re: Eliminarse a si mismo. Se puede optimizar?

Publicado: 27 Sep 2010, 08:45
por Ximorro
Pues sí.
Si quieres borrar en cuanto esté libre debes hacer un bucle así y entonces es necesario el BAT.
La otra es hacer una pausa de un par de segundos (con ping) y después borrar el exe con un comando "al vuelo", así no hace falta un archivo auxiliar.

Si usas el bat yo lo crearía en @TempDir, así no se ve aparecer junto al exe.

Por cierto, para no tener que poner el nombre del exe a mano en el código puedes usar @ScriptName (el nombre) o @ScriptFullPath (el nombre con todo el camino). Así de paso el código es más genérico, eso sí, eso también funciona con scripts no compilados así que ojo en desarrollo no vayas a borrarlo.
Puedes saber si un script está compilado con la macro @compiled (o mirando la extensión del archivo, pero para qué complicarse teniendo esa macro ;-) )

Re: Eliminarse a si mismo. Se puede optimizar?

Publicado: 28 Sep 2010, 01:55
por dertin
Gracias a ambos, hice los cambios que me comentaron :smt002
Elegí el metodo con el bucle GOTO, lo encuntro mas rapido y más seguro.

Código: Seleccionar todo

Func _Borrarme()

Local $tempBatch = @TempDir & "\temp"& @SEC & ".bat"
Local $dirProgram = @ScriptFullPath

If @compiled = 1 Then

	$file = FileOpen($tempBatch,1)

	If $file = -1 Then
		MsgBox(0,"Error","Error al crear " & $tempBatch)
		Return 2 ; Error al crear y escribir el archivo.
	EndIf

	FileWrite($file, ":Borrar" & @CRLF & "DEL " & $dirProgram & @CRLF & "IF EXIST " & $dirProgram & " GOTO Borrar" & @CRLF & "DEL " & $tempBatch)
	FileClose($file)

	Run($tempBatch,'',@SW_HIDE)

	Return 0 ; Operación realizada con exito.
	Exit
Else
	Return 1 ; Operación no realizada.
EndIf

EndFunc

If _Borrarme() = 2 Then
	MsgBox(0,"Error","Error al Borrarme")
	Exit
ElseIf _Borrarme() = 1 Then
	MsgBox(0,"Info","Operación no realizada.")
EndIf
:smt006 Att: dertin

Re: Eliminarse a si mismo. Se puede optimizar?

Publicado: 28 Sep 2010, 09:00
por Ximorro
¡A mandar! Sí que está quedando bien...

Una cosa, si estás en desarrollo está ejecutando la función dos veces, las dos para decirte que no lo ha ejecutado.
Es por poner la llamada tanto en el If como en el Else, creo que sería mejor ejecutarlo fuera del IF y tomar el retorno de la función en una variable, que es la que comprobarías, así sólo lanzará la función una vez. Es una tontería pero por afinar ;-)