2008. december 8., hétfő

How to create a program that deletes itself after running


Problem/Question/Abstract:

I would like to run a program that finishes by deleting itself (similar to the DOS TSR programs). Is this possible?

Answer:

Solve 1:

One technique is to use a batch file. It works on all versions of Windows. An example:

{ ... }
s := 'SelfDelete.bat';
s := ExtractFilePath(ParamStr(0)) + s;
assign(f, s);
rewrite(f);
writeln(f, ':f');
writeln(f, 'del "' + ParanStr(0));
writeln(f, 'if EXIST "' + ParamStr(0) + '" goto f');
writeln(f, 'del "' + s);
closefile(f);
WinExec(PChar(s), SW_HIDE)


Solve 2:

This simple method uses a Windows Registry entry, which in turn, makes Command.com to do the job for us, whenever the next Windows restart occurs. Add the following code to a procedure of your choice:

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls,
    Registry;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.Button1Click(Sender: TObject);
var
  APath: array[0..255] of char;
begin
  {Command.com does not support long paths, so convert to short}
  if GetShortPathName(PChar(ParamStr(0)), APath, SizeOf(APath) - 1) <> 0 then
  begin
    {Work with TRegistry}
    with TRegistry.Create do
    try
      {Set Root Key}
      RootKey := HKEY_LOCAL_MACHINE;
      {Open Key, creating key if it does not exist}
      if OpenKey('\Software\Microsoft\Windows\CurrentVersion\RunOnce', True) then
      begin
        {Add our String Value to the Key}
        WriteString('MyApp', 'command.com /c del ' + APath);
        {Close the Key}
        CloseKey;
      end;
    finally
      {Free TRegistry}
      free;
    end;
  end;
end;

This example makes use of ParamStr(0) to meet the expectations that the title of this article has elicited: By pointing to the path + filename of the application that executes this procedure, the program will in fact bring about the removal of itself. Windows NT/2000 Note: Users running programs that utilize this code, must have the right to modify the HKEY_LOCAL_MACHINE section of the Windows Registry.


Solve 3:

Try this (not tested under WinXP, but works under Win95, Win98, WinNT 4.0 and Win2000):

procedure DeleteExeAndDir;
var
  hModule: THandle;
  szModuleName, szDirName: array[0..MAX_PATH] of Char;
  hKrnl32: THandle;
  pExitProcess, pDeleteFile, pFreeLibrary, pUnmapViewOfFile, pRemoveDir: pointer;
  ExitCode: UINT;
var
  r: integer;
begin
  hModule := GetModuleHandle(nil);
  GetModuleFileName(hModule, szModuleName, sizeof(szModuleName));
  StrPCopy(szDirName, ExtractFileDir(szModuleName));
  hKrnl32 := 'kernel32');
pExitProcess := GetProcAddress(hKrnl32, 'ExitProcess');
pDeleteFile := GetProcAddress(hKrnl32, 'DeleteFileA');
pFreeLibrary := GetProcAddress(hKrnl32, 'FreeLibrary');
pUnmapViewOfFile := GetProcAddress(hKrnl32, 'UnmapViewOfFile');
pRemoveDir := GetProcAddress(hKrnl32, 'RemoveDirectoryA');
ExitCode := system.ExitCode;
SetCurrentDirectory(pchar(ExtractFileDir(szDirName)));
if ($80000000 and GetVersion()) <> 0 then
  {Win95, 98, Me}
  asm
    lea     eax, szModuleName
    lea     ecx, szDirName
    push    ExitCode
    push    0
    push    ecx
    push    pExitProcess
    push    eax
    push    pRemoveDir
    push    hModule
    push    pDeleteFile
    push    pFreeLibrary
    ret
  end
else
begin
  for r := 1 to 100 do
  begin
    CloseHandle(r shl 2);
  end;
  {CloseHandle(THANDLE(4));}
  asm
    lea     eax, szModuleName
    lea     ecx, szDirName
    push    ExitCode
    push    0
    push    ecx
    push    pExitProcess
    push    eax
    push    pRemoveDir
    push    hModule
    push    pDeleteFile
    push    pUnmapViewOfFile
    ret
  end
end;
end;


Solve 4:

program delself;

uses
  windows;

procedure DeleteSelf;
var
  module: HMODULE;
  buf: array[0..MAX_PATH - 1] of char;
  p: ULONG;
  hKrnl32: HMODULE;
  pExitProcess, pDeleteFile, pFreeLibrary: pointer;
begin
  module := GetModuleHandle(nil);
  GetModuleFileName(module, buf, sizeof(buf));
  CloseHandle(THandle(4));
  p := ULONG(module) + 1;
  hKrnl32 := GetModuleHandle('kernel32');
  pExitProcess := GetProcAddress(hKrnl32, 'ExitProcess');
  pDeleteFile := GetProcAddress(hKrnl32, 'DeleteFileA');
  pFreeLibrary := GetProcAddress(hKrnl32, 'FreeLibrary');
  asm
    lea eax, buf
    push 0
    push 0
    push eax
    push pExitProcess
    push p
    push pDeleteFile
    push pFreeLibrary
    ret
  end;
end;

begin
  DeleteSelf;
end.

Nincsenek megjegyzések:

Megjegyzés küldése