Quizás te has visto en alguna ocasión ante la necesidad de eliminar tu aplicación una vez que ha terminado de realizar su trabajo. Pero ya sabes que el Sistema Operativo Windows se protege a si mismo de muchas formas distintas, y una de ellas es no permitir borrar un archivo ejecutable mientras está siendo ejecutado.
Entonces ¿como es posible que una aplicación pueda ejecutar alguna instrucción dentro de su propio código para que la aplicación se borre a sí misma?
El secreto está en la función SelfDelete que te muestro en el código del ejemplo siguiente.
Después de probar múltiples formas de intentar conseguir este proposito (que las muestro todas dentro del código de la "unit1.pas" en forma de comentarios) he comprobado que la más efectiva y de código más conciso es la que te muestro.
Es muy importante entender que esta función solo puede ser llamada en el evento FormClose del Formulario principal de la aplicación, es decir, que debe ser llamada justo antes de que la aplicación se cierre. Esto es debido a que lo que hace la función es llamar al sistema operativo para que este cree una nueva ventana de comandos (no visible) y ejecute la instrucción "del" sobre nuestro archivo ejecutable. Esto podrá tener éxito si en el tiempo que transcurre entre la llamada a la función y su ejecución por parte del S.O. nuestra aplicación ya se ha cerrado y desaparecido de la lista de tareas activas que controla el sistema.
A continuación, puedes ver el código completo de la app, y si lo deseas puedes descargarlo todo (código y app) en un archivo "zip".
unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs; type TForm1 = class(TForm) procedure FormClose(Sender: TObject; var Action: TCloseAction); private { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation {$R *.dfm} uses shellapi; procedure SelfDelete; var szFile, szCmd: array [ 0 .. MAX_PATH - 1 ] of char; begin if((GetModuleFileName(0,szFile,MAX_PATH)<>0) and (GetShortPathName(szFile,szFile,MAX_PATH)<>0)) then begin lstrcpy(szCmd,'/c del '); lstrcat(szCmd,szFile); lstrcat(szCmd,' >> NUL'); if Windows.GetEnvironmentVariable('ComSpec',szFile,MAX_PATH)<>0 then ShellExecute(0,nil,szFile,szCmd,nil,SW_HIDE); end; end; { procedure SelfDelete1; var cmd, s : string; n:dword; begin // !!!! milisegundos de espera antes de borrar s:= '/C ping 1.1.1.1 -n 1 -w 3000 >> nul & del "'+paramstr(0)+'" >> nul'; setlength(cmd,256); n:=GetEnvironmentVariable('ComSpec', pchar(cmd), 255); if n<>0 then begin setlength(cmd,n); //WinExec(pchar(cmd + ' '+ s),sw_hide); ShellExecute(0, 'open', pchar(cmd), pchar(s), nil, sw_hide); end; end; procedure SelfDelete2; var s: string; f: textfile; begin s:= GetTmpFileName('.bat');; AssignFile(f,s); Rewrite(f); Writeln(f,':f'); Writeln(f, 'del "'+ Paramstr(0)+'"'); WriteLn(f,'if EXIST "'+ pARAMSTR(0) + '" GOTO f'); WriteLn(f,'del "'+ s +'"'); CloseFile(f); WinExec(pchar(s), sw_hide); end; procedure SelfDelete3; var F: TextFile; batName: string; pi: TProcessInformation; si: TStartupInfo; begin batName := ExtractFilePath(ParamStr(0)) + '$$$$$$$$.bat'; AssignFile(F,batName); Rewrite(F); Writeln(F,':try'); Writeln(F,'del "'+ParamStr(0)+'"'); Writeln(F,'if exist "'+ ParamStr(0)+'"'+' goto try'); Writeln(F,'del "' + batName + '"' ); CloseFile(F); FillChar(si, SizeOf(si), $00); si.dwFlags := STARTF_USESHOWWINDOW; si.wShowWindow := SW_HIDE; //MessageBox(0,'Antes de lanzar el bat','Dentro de SelfDelete',MB_OK); //Quitamos los atributos de oculto y solo lectura para que no falle el .bat SetFileAttributes( PChar( ParamStr(0) ), 0 ); if CreateProcess( nil, PChar(batName), nil, nil, False, IDLE_PRIORITY_CLASS, nil, nil, si, pi ) then begin CloseHandle(pi.hThread); CloseHandle(pi.hProcess); //MessageBox(0,'Lanzado el proceso bat','Dentro de SelfDelete',MB_OK); end; //MessageBox(0,'Lanzado el proceso bat','Dentro de SelfDelete',MB_OK); Halt; end; procedure SelfDelete4; var szFile, szCmd: array [ 0 .. MAX_PATH - 1 ] of char; begin //if((GetModuleFileName(0,szFile,MAX_PATH)<>0) and // (GetShortPathName(szFile,szFile,MAX_PATH)<>0)) then begin lstrcpy(szCmd,'/c del '); //lstrcat(szCmd,szFile); lstrcat(szCmd, pchar('"'+Paramstr(0)+'"')); lstrcat(szCmd,' >> NUL'); if Windows.GetEnvironmentVariable('ComSpec',szFile,MAX_PATH)<>0 then ShellExecute(0,nil,szFile,szCmd,nil,SW_HIDE); end; end; procedure SelfDelete5; var szFile, szCmd: array [ 0 .. MAX_PATH - 1 ] of char; begin if((GetModuleFileName(0,szFile,MAX_PATH)<>0) and (GetShortPathName(szFile,szFile,MAX_PATH)<>0)) then begin //showmessage(szfile); lstrcpy(szCmd,'/c del '); lstrcat(szCmd,szFile); lstrcat(szCmd,' >> NUL'); if Windows.GetEnvironmentVariable('ComSpec',szFile,MAX_PATH)<>0 then begin //showmessage(szfile+szCmd); ShellExecute(0,nil,szFile,szCmd,nil,SW_HIDE); //WinExec(pchar(szFile + ' '+ szCmd),sw_hide); end; end; end; } procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction); begin SelfDelete; end; end.