Duda: Actualizador y borrado

Aquí puedes preguntar o compartir tus dudas y conocimientos acerca del programa
Hola tengo una duda un tanto raro, no encuentro el proyecto a ver si lo encuentro, como el titulo reza. Cual es la mejor manera de borrar el propio exe actualizador si el mismo actualizador una vez cerrado no se deja borrar quizas por estar en uso todavia.

Quiero decir, bajo un exe que actualiza algo una carpeta o archivos incluso, una vez actualizado este borra al no ser util y haber cumplido con su funcion. He probado hacerlo desde el evento onclose y no hace nada borra otros archivos pero no el actualizador.

Por cierto como se le dice al propio actualizador la ruta desde el cual esta arrancando ( el actualizador esta hecho en modo web exe )he probado la variable _SourceFilename y solo te dice el nombre del archivo y su extension lo cual es correcto pero no te dice la ruta. Hago uso del _SourceDrive y no sale porque al ser web exe al abrirlo descomprime los archivos en la maldita carpeta temp bajo una carpeta con un nombre como ir_temp01 o algo asi.

Alguien tiene una idea de como hacerlo? No hace falta que me den codigo, solo ideas o los nombre de las funciones ams si es que se puede algun dll o algo

Hola mi buen, aqui lo que convendria hacer es apoyarse de un "tercero", crea otro ejecutable el cual corra en modo silencioso y se encargue de borrar todo rastro una vez de que tu actualizador haya hecho su trabajo.

La manera mas sencilla es apoyarse de los procesos y el regedit de widows, timer de ams y demas "herramientas" que se te ocurran.

Por ejemplo, Creas el actualizador y el eliminador:

Ambos se ejecutaran simultaneamente, para esto el actualizador debe ejecutar al eliminador desde su inicio y en tiempo de ejecucion el eliminador nada mas tendra que verificar que el actualizador se cierre para poder eliminar todo lo referente a el, de que manera? Pues manejando en el evento On Timer del eliminador los procesos de Windows; los estara verificando cada 5 segundos por ejemplo desde su inicio y cuando falte el proceso del actualizador entonces procedera a eliminar todo lo referente al mismo.

A mi se me ocurre que al inicio del actualizador cree una clave de registro para que esta sirva como "llave" del eliminador, es decir: si existe esa clave de registro el eliminador funciona, de lo contrario no funcionara en "stand-alone", asi ,si el usuario lo encuentra pues sencillamente no lo podra ejecutar porque al momento de que el eliminador se cierre solo tambien eliminara esa entrada de registro, tambien podria ser un temporal...

Solo tendras que identificar plenamente la basura que podria dejar el actualizador, lo puedes hacer con loops para evitarte trabajo de mas, como sabes los ejecutables web de ams crean carpetas indexadas de manera logica para que no se confundan si utilizas mas de una aplicacion (de ams) simultanea.

Ya como plus y si deseas eliminar tambien al actualizador pues con un simple _SourceFolder.._SourceFilename podrias ingresar a un .txt temporal la ruta del iactualizador para que el eliminador joda todo lo referente al mismo, si haces esto lo que te recomiendo que hagas es que el eliminador no contenga dato alguno pues este quedara dentro de la PC del usuario, como se ejecutara entonces? Pues asignando un script que contendra toda la informacion a eliminar, este script sera creado por el actualizador en alguna parte del PC y llamado por el eliminador en su momento y eliminado cuando el "eliminador" finalice su trabajo, de esta manera solo quedara un ejecutable casi vacio dentro del PC del usuario.

Tambien podrias utilizar la funcion File.DeleteOnReboot() que seria la mejor opcion y mas creible para el usuario, si utilizas esta opcion no te olvides de indicar al usuario que guarde todo su trabajo pues al terminar de actualizar la maquina se reiniciara.

En fin, es cuestion de ingenio.
Saludos viejo ;)

En realidad lo de sacar el _SourceFolder al Web ejecutable comprimido es fácil, sólo que está un poco escondido en la ayuda de ams!!

Web/Email Executable

Imagen

Como sabrás _CommandLineArgs es una tabla
LineaDeCommandos = (_CommandLineArgs[1]); -- Te devolverá algo así "SFXSOURCE:C:\Temp\launcher.exe"
SourceFolder = LineaDeCommandos:gsub("SFXSOURCE:", "")  -- Así te queda la ruta pura
Eso es todo, PD: el :gsub es como si hicieras string.gsub() o en String.Replace()

Re:

Hola Meta:

"[..]Ambos se ejecutaran simultaneamente, para esto el actualizador debe ejecutar al eliminador desde su inicio y en tiempo de ejecucion el eliminador nada mas tendra que verificar que el actualizador se cierre para poder eliminar todo lo referente a el, de que manera? Pues manejando en el evento On Timer del eliminador los procesos de Windows; los estara verificando cada 5 segundos por ejemplo desde su inicio y cuando falte el proceso del actualizador entonces procedera a eliminar todo lo referente al mismo.[...]"

Te refieres a usar las funciones service del ams para arrancar la aplicacion nodriza encargada de borrar al actualizador no? que requisitos hay que tener para usar la funcion service, tiene que estar el programa instalado en alguna carpeta especial tipo windows o archivos de programa?

"[...]A mi se me ocurre que al inicio del actualizador cree una clave de registro para que esta sirva como "llave" del eliminador, es decir: si existe esa clave de registro el eliminador funciona, de lo contrario no funcionara en "stand-alone", asi ,si el usuario lo encuentra pues sencillamente no lo podra ejecutar porque al momento de que el eliminador se cierre solo tambien eliminara esa entrada de registro, tambien podria ser un temporal...[...]"

Buena idea miraré a ver como es la cosa

"[...]Ya como plus y si deseas eliminar tambien al actualizador pues con un simple _SourceFolder.._SourceFilename podrias ingresar a un .txt temporal la ruta del actualizador para que el eliminador joda todo lo referente al mismo, si haces esto lo que te recomiendo que hagas es que el eliminador no contenga dato alguno pues este quedara dentro de la PC del usuario, como se ejecutara entonces? Pues asignando un script que contendra toda la informacion a eliminar, este script sera creado por el actualizador en alguna parte del PC y llamado por el eliminador en su momento y eliminado cuando el "eliminador" finalice su trabajo, de esta manera solo quedara un ejecutable casi vacio dentro del PC del usuario.[...]"

Por script entiendo que si no debo meter datos internos en el eliminador o eraser ( suena mas pelicurero jajaja ) tendria que hacerlo con datos desde regedit o por ini no?

"[...]Tambien podrias utilizar la funcion File.DeleteOnReboot() que seria la mejor opcion y mas creible para el usuario, si utilizas esta opcion no te olvides de indicar al usuario que guarde todo su trabajo pues al terminar de actualizar la maquina se reiniciara.[...]"

Ostias no me acordaba de esa funcion! gracias por recordarlo jajaja

TheDary gracias por la info, ni lo sabia esta jodidamente escondida en el puto help jajaja

yo para no complicarme mucho utilizo las propiedades que tiene el Winrar, para crear EXES, con parametros pre definidos, con todo ese conjunto se me hace más facil, por ejemplo;

Yo tenia un proyecto que se actualizaba automáticamente cuando detectaba que estaba des actualizado al ver que la versión del Exe nativo era comprobado (a travez de su .Version), por la info de un .INI que acababa de descargar ese mismo Exe des actualizado

Al hacer esta acción descargaba el nuevo exe (que no era ni mas ni menos que el programa mismo, actualizado por supuesto con los archivos necesarios y compromidos y creados en EXE con el winrar) a travez del enlace que le proporcionaba el mismo .INI ya descargado anteriormente ,

Claro ese .INI, tenia que cambiar su enlace hacia el actualizador más reciente para evitar una actualización engorrosa y larga... como esta;

Programa 1.0 , se abre y comprueba actualización y descarga programa 2.0 (pero ya hay programa 5.0 entonces...)
el 1.0 se actualiza a la 2.0, .. .. luego, se abre el 2.0 y comprueba....
Programa 2.0... comprueba y se actualiza y descarga programa 3.0....
Programa 3.0, se abre y comprueba, y se actualiza y descarga a programa 4.0...
Programa 4.0, se abre y comprueba, y se actualiza y descarga a programa 5.0..., que es finalmente la última version que debio descargarse primero...

La forma correcta debio ser asi;

Programa 1.0, se abre y comprueba, y se actualiza directamente a la 5.0...
Y ya esta! :yes:

Espero haberte ayudado, si deseas me pides el código y te lo paso! :D

estaria bien que lo postearas ;)

estaria bien que lo postearas ;)

A pedido del publico; Esto lo hice hace como 1 año y medio;

Es necesario poner el codigo en el notepad++ sin "ajuste de linea", ya que la programación es jerarquíca, y no se ve bien porque el foro no esta adaptado a esa resolución que se necesita...

Ojo; no utilice el regedit, ni nada fuera del comportamiento normal, ya que posiblemente iban a utilizar la aplicación sin permisos de administrador

Primero, esto lo puse en "Pre load" de la página:
buskeda_reinicio = File.Find(_SourceFolder, "reinicio_kk.ini", true, false, nil);
if (buskeda_reinicio) then
	File.Delete(_SourceFolder.."\\reinicio_kk.ini", false, false, false, nil);
	error = Application.GetLastError();
    if error ~= 0 then
		Dialog.Message("Error de Borrado - N10001", "Ocurrio un error borrando el archivo 'reinicio_kk.ini', este archivo le indica al Juego\nque debe reiniciarse despues de una operación generalmente de restablecimiento, pero\nel sistema no a podido borrarlo automaticamente, es crucial que lo hagas manualmente.\n \nSe procederá a abrir la carpeta contenedora...", MB_OK, MB_ICONINFORMATION, MB_DEFBUTTON1);	
		File.ExploreFolder(_SourceFolder, SW_MAXIMIZE);
		os.exit();
	end	
end


busc_ctu = File.Find(_SourceFolder, "juego_actualizador.exe", false, false, nil, nil);
if (busc_ctu) then
	File.Delete(_SourceFolder.."\\juego_actualizador.exe", false, false, false, nil);
	File.Delete(_SourceFolder.."\\*.tmp", false, false, false, nil);
end
Esto lo puse en On show de la página
Label.SetText("Label1", "Verificando Actualizaciones...");
testear_actualizacion = HTTP.TestConnection(""..web_servidor.."/juego/actualizaciones/2.0.0.0/2.0.0.0.ini", 20, 80, nil, nil);
if (testear_actualizacion) then
	HTTP.Download(""..web_servidor.."/juego/actualizaciones/2.0.0.0/2.0.0.0.ini",_TempFolder.."\\2.0.0.0.zip", MODE_BINARY, 20, 80, nil, nil, nil);
	error5 = Application.GetLastError();
	StatusDlg.Hide();
    if error5 ~= 0 then
		Paragraph.SetVisible("Paragraph1", false);
		Progress.SetVisible("Progress1", false);
		Web.SetVisible("Web1", false);
		Web.SetVisible("Web2", true);
		Dialog.Message("Error de Descarga - K10002", "Ocurrio un error descargando el archivo verificador\nCierra el Juego y abrelo otra vez...", MB_OK, MB_ICONINFORMATION, MB_DEFBUTTON1);	
		Application.Exit(0);		
		else
		Zip.Extract(_TempFolder.."\\2.0.0.0.zip", {"*.*"}, _TempFolder , true, true, "miclavequequiero", ZIP_OVERWRITE_ALWAYS, nil);
		error6 = Application.GetLastError();
		StatusDlg.Hide();
		if error6 ~= 0 then
			Dialog.Message("Error de Extracción - K20002", "Ocurrio un error extrayendo el archivo actualizador\nCierra el Juego y abrelo otra vez...", MB_OK, MB_ICONINFORMATION, MB_DEFBUTTON1);	
			Application.Exit(0);
			else
			File.Delete(_TempFolder.."\\2.0.0.0.zip", false, false, false, nil);
			Crypto.Base64DecodeFromFile(_TempFolder.."\\2.0.0.0.ini", _TempFolder.."\\2.0.0.0_2.ini");
			error7 = Application.GetLastError();
			if (error7 ~=0) then
				Dialog.Message("Error de Descodificación - K30002", "Ocurrio un error descodificando el archivo actualizador\nCierra el Juego y abrelo otra vez...", MB_OK, MB_ICONINFORMATION, MB_DEFBUTTON1);
				Application.Exit(0);
				else
				File.Delete(_TempFolder.."\\2.0.0.0.ini", false, false, true, nil);
				if (Application.GetLastError() ~= 0) then
					Dialog.Message("Error de Borrado - K20002", "Ocurrio un error borrando el archivo actualizador\nCierra el Juego y abrelo otra vez...", MB_OK, MB_ICONINFORMATION, MB_DEFBUTTON1);	
					Application.Exit(0);
					else
					File.Rename(_TempFolder.."\\2.0.0.0_2.ini", _TempFolder.."\\2.0.0.0.ini");
					error8 = Application.GetLastError();
					if (error8 ~= 0) then
						Dialog.Message("Error de Renombramiento - K10003", "Ocurrio un error renombrando el archivo verificador\nCierra el Juego y abrelo otra vez...", MB_OK, MB_ICONINFORMATION, MB_DEFBUTTON1);	
						Application.Exit(0);
						else
						version_actual = INIFile.GetValue(_TempFolder.."\\2.0.0.0.ini", "Datos Juego", "Version Actual");
						error9 = Application.GetLastError();
						if (error9 ~=0) then
							Dialog.Message("Error de Verificación - K20001 A", "Ocurrio un error verificando la versión del juego\nCierra el Juego y abrelo otra vez...", MB_OK, MB_ICONINFORMATION, MB_DEFBUTTON1);	
							Application.Exit(0);
							else
							version_juego = File.GetVersionInfo(_SourceFolder.."\\juego.exe").ProductVersion;
							error10 = Application.GetLastError();
							if (error10 ~=0) then
						    	Dialog.Message("Error de Verificación - K20001 B", "Ocurrio un error verificando la versión del juego\nCierra el Juego y abrelo otra vez...", MB_OK, MB_ICONINFORMATION, MB_DEFBUTTON1);	
								Application.Exit(0);
								else
 								compara_versiones = String.CompareFileVersions(version_actual, version_juego);-- con esta accion nos compara dos strings ( De versiones tipo 1.0.0.0) y debuelve 1 si el paramaetro a es mayor que el b.
								if (compara_versiones ~= 1) then-- si la version no es mayor...
									File.Delete(_TempFolder.."\\2.0.0.0.ini", false, false, true, nil);
									Label.SetText("Label1", "Posees la Última versión!!!");
									Application.Sleep(500);
									Page.Jump("logeo");
									else 
									Label.SetText("Label1", "Actualizacion Disponible!!!");
									Application.Sleep(500);
									Label.SetVisible("Label1", false);
									Paragraph.SetText("Paragraph1", "Descargando actualizaciones...");
									Progress.SetVisible("Progress1", true);
									function DownloadCallback (nDownloaded, nTotal, TransferRate, SecondLeft, SecondsLeftFormat, Message)
									sDownloaded = String.GetFormattedSize(nDownloaded, FMTSIZE_AUTOMATIC, true);
									sTotal = String.GetFormattedSize(nTotal, FMTSIZE_AUTOMATIC, true);
									Paragraph.SetText("Paragraph1", "Tiempo Restante: "..SecondsLeftFormat.."\n \nDescargado: " .. sDownloaded .. " / " .. sTotal);
									nPos=(nDownloaded / nTotal) * 65534
									Progress.SetCurrentPos("Progress1",nPos );
			     					return true
									end
									Progress.SetRange("Progress1", 0, 65534);
									url_actualizador = INIFile.GetValue(_TempFolder.."\\2.0.0.0.ini", "Datos Juego", "Url Actualizador");
									HTTP.Download(url_actualizador, _TempFolder.."\\2.0.0.0.zip", MODE_BINARY, 10, 80, nil, nil, DownloadCallback);
									error11 = Application.GetLastError();
									StatusDlg.Hide();
    								if error11 ~= 0 then
    									Paragraph.SetVisible("Paragraph1", false);
										Progress.SetVisible("Progress1", false);
										Web.SetVisible("Web1", false);
										Web.SetVisible("Web2", true);
										Dialog.Message("Error de Descarga - K10003", "Ocurrio un error descargando el instalador actualizador\nCierra el Juego y abrelo otra vez...", MB_OK, MB_ICONINFORMATION, MB_DEFBUTTON1);	
										Application.Exit(0);		
										else
										md5_actualizador1 = Crypto.MD5DigestFromFile(_TempFolder.."\\2.0.0.0.zip");
										md5_actualizador2 = INIFile.GetValue(_TempFolder.."\\2.0.0.0.ini", "Datos Juego", "MD5 Actualizador");
										if (md5_actualizador1 == md5_actualizador2) then
											File.Delete(_TempFolder.."\\2.0.0.0.ini", false, false, false, nil);
											if (Application.GetLastError() ~= 0) then
												Dialog.Message("Error de Borrado - K20003", "Ocurrio un error borrando el archivo verificador\nCierra el Juego y abrelo otra vez...", MB_OK, MB_ICONINFORMATION, MB_DEFBUTTON1);	
												Application.Exit(0);
												else
												Paragraph.SetText("Paragraph1", "Instalando Actualización...");
												function ZipCallback (String, Parcent, Status)
												Progress.SetCurrentPos("Progress1", Parcent);
												return true
												end
												Zip.Extract(_TempFolder.."\\2.0.0.0.zip", {"*.*"}, _SourceFolder , true, true, "miotraclavexD", ZIP_OVERWRITE_ALWAYS, ZipCallback);
												error12 = Application.GetLastError();
												StatusDlg.Hide();
												if error12 ~= 0 then
													Dialog.Message("Error de Extracción - K20002", "Ocurrio un error actualizando el sistema\nCierra el Juego y abrelo otra vez...", MB_OK, MB_ICONINFORMATION, MB_DEFBUTTON1);	
													Application.Exit(0);
													else
													File.Delete(_TempFolder.."\\2.0.0.0.zip", false, false, false, nil);
													if (Application.GetLastError() ~= 0) then
													Dialog.Message("Error de Borrado - K20004", "Ocurrio un error borrando el zip actualizador\nCierra el Juego y abrelo otra vez...", MB_OK, MB_ICONINFORMATION, MB_DEFBUTTON1);	
													Application.Exit(0);
													else
													File.Delete(_TempFolder.."\\2.0.0.0.ini", false, false, true, nil);
													Paragraph.SetText("Paragraph1", "Actualizacion Completa!!!");
													Application.Exit();
													end
												end	
											end
											else
											Dialog.Message("Error de Verificación - K20001", "Se a detecta que el zip actualizador que se ha descargado\nno es el correcto para la versión que tienes actualmente\n \nCierra el Juego y abrelo otra vez...", MB_OK, MB_ICONINFORMATION, MB_DEFBUTTON1);	
											Application.Exit(0);
										end
									end
								end		
							end	
						end
					end
				end
			end
		end	
	end
	else
	Dialog.Message("Error de Verificación - K30002", "Ocurrio un error verificando si hay actualizaciones disponibles,\nposiblemente el servidor maestro se este actualizando,\n \n Intentelo nuevamente en unos 5 minutos...", MB_OK, MB_ICONINFORMATION, MB_DEFBUTTON1);	
	Application.Exit(0);
end
Y este en "On Close"
busca_reinicio = File.Find(_SourceFolder, "reinicio_kk.ini", false, false, nil, nil);
if (busca_reinicio) then
	File.Delete(_SourceFolder.."\\reinicio_kk.ini", false, false, false, nil);
	error1 = Application.GetLastError();
	if (error1 ~=0) then
		Dialog.Message("Error de Borrado - N10002", "Ocurrio un error borrando el archivo reinicio_kk.ini, que es el que indica al sistema\nque el Juego debe reiniciarce, por favor borralo y abre el Juego otra vez...", MB_OK, MB_ICONINFORMATION, MB_DEFBUTTON1);	
		File.ExploreFolder(_SourceFolder, SW_MAXIMIZE);
		Application.Exit(0);
		else
		busca_actualizado = File.Find(_SourceFolder, "juego_actualizador.exe", false, false, nil, nil);
		if (busca_actualizado) then
			File.Run(_SourceFolder.."\\juego_actualizador.exe", "", "", SW_HIDE, false);
			else
			File.Run(_SourceFolder.."\\juego.exe", "", "", SW_SHOWNORMAL, false);
		end	
	end
	else
	busca_actualizado2 = File.Find(_SourceFolder, "juego_actualizador.exe", false, false, nil, nil);
	if (busca_actualizado2) then
		File.Run(_SourceFolder.."\\juego_actualizador.exe", "", "", SW_HIDE, false);
	end
end	
Notece que mi programación es muy conservadora, osea que si no se cumple una regla, no seguirá el proceso, ya que si lo hiciera estaría siguiendo un camino sin terminar, eso siempre trato de hacer cuando programo. se que posiblemente este lleno de codigo sobrante, que se puede reducir "a lo pabloko", lo digo asi porque seguro biene pabloko y reduce las 300 lineas por tan solo 5 :) :) :), pero bueno en ese tiempo era bien novato y con el poco conocimiento que tenia, logré hacer esto :pc: si les sirve para algo, que bueno!

Joder sarumanice jajaja menudo currelas tendre que leer el codigo que has posteado, al final hice lo que me explico Metafunken pero tu alternativa me ha dado otra idea en terminos de servidores, gracias por la explicacion!

Amigo sarumanice la próxima que vayas a postear un código de esas dimensiones considera la posibilidad de subir un apz, más facil de comprender y vas al grano.

Re:

Thedary escribió:Amigo sarumanice la próxima que vayas a postear un código de esas dimensiones considera la posibilidad de subir un apz, más facil de comprender y vas al grano.
:) :) :) lo siento, quise compartir el código antes de caerme de sueño, ya que llevaba dos días sin dormir :hypno:
carsonzillo escribió:Joder sarumanice jajaja menudo currelas tendre que leer el codigo que has posteado, al final hice lo que me explico Metafunken pero tu alternativa me ha dado otra idea en terminos de servidores, gracias por la explicacion!
Que bueno que te aya ayudado mi código, lo hice hace más de año, obviamente se puede mejorar y acortar, pero da flojera :) y el proyecto en el cual lo utilice, ya se cancelo, aunque eso no significa que sea totalmente funcional, al 100%

Saludos a todos en el foro :pc: