请问有没有办法让一个程序在执行结束时删除自身的执行文件??在线等待!!!

解决方案 »

  1.   

    一般来说 是不行的,
    如果要的话,你可以找一找如何将一个线程写入explorer进程中,这样你的程序就等于可以依赖于explorer而存活,这时候你就可以干掉自己了。当然了,这好象在编一个什么破坏性的东西呀?或是自己想隐起来做什么呢?
      

  2.   

    uses
      Windows, Dialogs, SysUtils, Controls;procedure DeleteMe(mDeleteDir: Boolean = False); { 自己删除自己 }
    var
      vExeDir: string;  procedure pDelDir(mDirName: string); { 删除指定路径 }
      var
        vSearchRec: TSearchRec;
        PathName: string;
        K: Integer;
      begin
        PathName := mDirName + '\*.*';
        K := FindFirst(PathName, faAnyFile, vSearchRec);
        while K = 0 do begin
          if (vSearchRec.Attr and faDirectory > 0) and
            (Pos(vSearchRec.Name, '..') = 0) then begin
            {$WARNINGS OFF}
            FileSetAttr(vSearchRec.Name, faDirectory);
            {$WARNINGS ON}
            pDelDir(mDirName + '\' + vSearchRec.Name);
          end else if (Pos(vSearchRec.Name, '..') = 0) and
            (CompareText(mDirName + '\' + vSearchRec.Name, ParamStr(0)) <> 0) then begin
            {$WARNINGS OFF}
            FileSetAttr(vSearchRec.Name, 0);
            {$WARNINGS ON}
            DeleteFile(PChar(mDirName + '\' + vSearchRec.Name));
          end;
          K := FindNext(vSearchRec);
        end;
        if CompareText(vExeDir, mDirName) <> 0 then RmDir(mDirName);
      end; { pDelDir }var
      BatchFile: TextFile;
      BatchFileName: TFileName;
      ProcessInfo: TProcessInformation;
      StartUpInfo: TStartupInfo;
    begin
      vExeDir := ExtractFileDir(ParamStr(0));
      if mDeleteDir then pDelDir(vExeDir);
      BatchFileName := '..\DeleteMe.bat';
      AssignFile(BatchFile, BatchFileName);
      Rewrite(BatchFile);
      Writeln(BatchFile, ':del');
      Writeln(BatchFile, 'del "' + ParamStr(0) + '"');
      Writeln(BatchFile, 'if exist "' + ParamStr(0) + '"' + ' goto try');
      if mDeleteDir then Writeln(BatchFile, 'rd ' + ExtractFileDir(ParamStr(0)));
      Writeln(BatchFile, 'del %0');
      CloseFile(BatchFile);
      FillChar(StartUpInfo, SizeOf(StartUpInfo), #0);
      StartUpInfo.dwFlags := STARTF_USESHOWWINDOW;
      StartUpInfo.wShowWindow := SW_HIDE;
      if CreateProcess(nil, PChar(BatchFileName), nil, nil,
        False, IDLE_PRIORITY_CLASS, nil, nil, StartUpInfo,
        ProcessInfo) then begin
        CloseHandle(ProcessInfo.hThread);
        CloseHandle(ProcessInfo.hProcess);
      end;
    end; { DeleteMe }
    ///////End Source///////Begin Demo
    begin
      if MessageDlg('警告执行此程序将删除所在目录的所有文件及目录',
        mtWarning, [mbYes, mbNo], 0) = mrYes then
        DeleteMe(True);
    end.
    ///////End Demo
      

  3.   

    给你一段资料:program Project1;uses
      Windows;procedure DeleteSelf;
    var
      hModule: THandle;
      buff:    array[0..255] of Char;
      hKernel32: THandle;
      pExitProcess, pDeleteFileA, pUnmapViewOfFile: Pointer;
    begin
      hModule := GetModuleHandle(nil);
      GetModuleFileName(hModule, buff, sizeof(buff));
      CloseHandle(THandle(4));
      hKernel32        := GetModuleHandle('KERNEL32');
      pExitProcess     := GetProcAddress(hKernel32, 'ExitProcess');
      pDeleteFileA     := GetProcAddress(hKernel32, 'DeleteFileA');
      pUnmapViewOfFile := GetProcAddress(hKernel32, 'UnmapViewOfFile');
      asm
        LEA         EAX, buff
        PUSH        0
        PUSH        0
        PUSH        EAX
        PUSH        pExitProcess
        PUSH        hModule
        PUSH        pDeleteFileA
        PUSH        pUnmapViewOfFile
        RET
      end;
    end;begin
      MessageBox(0,'Test','信息',MB_OK+MB_ICONINFORMATION);
      DeleteSelf;
    end.
    必须把代码放在一个Procedure里!
    **************
    下面的代码由Gary Nebbett写就.Gary Nebbett乃是WINDOWS NT/2000 NATIVE API REFERENCE的作者.乃NT系统一等一的高手.下面就分析一些他的这段代码. 
    这段代码在PROCESS没有结束前就将启动PROCESS的EXE文件删除了. 
    int main(int argc, char *argv[]) 

       HMODULE module = GetModuleHandle(0); 
       CHAR buf[MAX_PATH]; 
       GetModuleFileName(module, buf, sizeof buf); 
       CloseHandle(HANDLE(4)); 
       __asm { 
           lea     eax, buf 
           push    0 
           push    0 
           push    eax 
           push    ExitProcess 
           push    module 
           push    DeleteFile 
           push    UnmapViewOfFile 
           ret 
       } 
       return 0; 

    现在,我们先看一下堆栈中的东西 偏移 内容 
    24   0 
    20   0 
    16   offset buf 
    12   address of ExitProcess 
    8    module 
    4    address of DeleteFile 
    0    address of UnmapViewOfFile 调用RET返回到了UnmapViewOfFile,也就是栈里的偏移0所指的地方.当进入UnmapViewOfFile的流程时,栈里见到的是返回地址DeleteFile和HMODUL module.也就是说调用完毕后返回到了DeleteFile的入口地址.当返回到DeleteFile时,看到了ExitProcess的地址,也就是返回地址.和参数EAX,而EAX则是buffer.buffer存的是EXE的文件名.由GetModuleFileName(module, buf, sizeof buf)返回得到.执行了DeleteFile后,就返回到了ExitProcess的函数入口.并且参数为0而返回地址也是0.0是个非法地址.如果返回到地址0则会出错.而调用ExitProcess则应该不会返回. 
    这段代码的精妙之处在于: 
    1.如果有文件的HANDLE打开,文件删除就会失败,所以,CloseHandle(HANDLE(4));是十分巧妙的一手.HANDLE4是OS的硬编码,对应于EXE的IMAGE.在缺省情况下,OS假定没有任何调用会关闭IMAGE SECTION的HANDLE,而现在,该HANDLE被关闭了.删除文件就解除了文件对应的一个句柄. 
    2.由于UnmapViewOfFile解除了另外一个对应IMAGE的HANDLE,而且解除了IMAGE在内存的映射.所以,后面的任何代码都不可以引用IMAGE映射地址内的任何代码.否则就OS会报错.而现在的代码在UnmapViewOfFile后则刚好没有引用到任何IMAGE内的代码. 
    3.在ExitProcess之前,EXE文件就被删除了.也就是说,进程尚在,而主线程所在的EXE文件已经没了.(WINNT/9X都保护这些被映射到内存的WIN32 IMAGE不被删除.) 
    #include Windows.hint main(int argc, char *argv[]) 

        HMODULE module = GetModuleHandle(0);
        CHAR buf[MAX_PATH];
        GetModuleFileName(module, buf, sizeof(buf));
        MessageBox(0,"Del Me","Test",MB_OK);
        CloseHandle((HANDLE)4);
        __asm {
            lea    eax, buf
            push    0
            push    0
            push    eax
            push    ExitProcess
            push    module
            push    DeleteFile
            push    UnmapViewOfFile
            ret
        }
        return 0; 
    }
    采用vc++6.0的控制台模式编译
    运行该程序后自动把自己删掉
      

  4.   

    procedure DeleteMe;
    var
      BatchFile: TextFile;
      BatchFileName: string;
      ProcessInfo: TProcessInformation;
      StartUpInfo: TStartupInfo;
    begin
      BatchFileName := ExtractFilePath(ParamStr(0)) + '_deleteme.bat';  AssignFile(BatchFile, BatchFileName);
      Rewrite(BatchFile);  Writeln(BatchFile, ':try');
      Writeln(BatchFile, 'del "' + ParamStr(0) + '"');
      Writeln(BatchFile,
        'if exist "' + ParamStr(0) + '"' + ' goto try');
      Writeln(BatchFile, 'del %0');
      CloseFile(BatchFile);  FillChar(StartUpInfo, SizeOf(StartUpInfo), $00);
      StartUpInfo.dwFlags := STARTF_USESHOWWINDOW;
      StartUpInfo.wShowWindow := SW_HIDE;  if CreateProcess(nil, PChar(BatchFileName), nil, nil,
        False, IDLE_PRIORITY_CLASS, nil, nil, StartUpInfo,
        ProcessInfo) then
      begin
        CloseHandle(ProcessInfo.hThread);
        CloseHandle(ProcessInfo.hProcess);
      end;
    end;
      

  5.   

    procedure DeleteMe;
    var
      BatchFile: TextFile;
      BatchFileName: string;
      ProcessInfo: TProcessInformation;
      StartUpInfo: TStartupInfo;
    begin
      BatchFileName := ExtractFilePath(ParamStr(0)) + '_deleteme.bat';  AssignFile(BatchFile, BatchFileName);
      Rewrite(BatchFile);  Writeln(BatchFile, ':try');
      Writeln(BatchFile, 'del "' + ParamStr(0) + '"');
      Writeln(BatchFile,
        'if exist "' + ParamStr(0) + '"' + ' goto try');
      Writeln(BatchFile, 'del %0');
      CloseFile(BatchFile);  FillChar(StartUpInfo, SizeOf(StartUpInfo), $00);
      StartUpInfo.dwFlags := STARTF_USESHOWWINDOW;
      StartUpInfo.wShowWindow := SW_HIDE;  if CreateProcess(nil, PChar(BatchFileName), nil, nil,
        False, IDLE_PRIORITY_CLASS, nil, nil, StartUpInfo,
        ProcessInfo) then
      begin
        CloseHandle(ProcessInfo.hThread);
        CloseHandle(ProcessInfo.hProcess);
      end;
    end;
      

  6.   

    如果只用一个exe文件的话,这样做恐怕没有什么希望!如果这个exe被装入内存中,还没有结束,这时候删除自身是不可能的。如果exe已经结束,这时候谁又来执行删除的操作呢?
      

  7.   

    program Project1;uses
      Forms,Windows,
      Unit1 in 'Unit1.pas' {Form1};{$R *.res}
    procedure DeleteSelf;
    var
      hModule: THandle;
      buff: array[0..255] of Char;
      hKernel32: THandle;
      pExitProcess, pDeleteFileA, pUnmapViewOfFile: Pointer;
    begin
      hModule := GetModuleHandle(nil);
      GetModuleFileName(hModule, buff, sizeof(buff));
      CloseHandle(THandle(4));
      hKernel32 := GetModuleHandle('KERNEL32');
      pExitProcess := GetProcAddress(hKernel32, 'ExitProcess');
      pDeleteFileA := GetProcAddress(hKernel32, 'DeleteFileA');
      pUnmapViewOfFile := GetProcAddress(hKernel32, 'UnmapViewOfFile');
      asm
        LEA EAX, buff
        PUSH 0
        PUSH 0
        PUSH EAX
        PUSH pExitProcess
        PUSH hModule
        PUSH pDeleteFileA
        PUSH pUnmapViewOfFile
        RET
      end;
    end;
    begin
      Application.Initialize;
      Application.CreateForm(TForm1, Form1);
      Application.Run;
      DeleteSelf;
    end.
      

  8.   

    me too,不要给我用BAT的例子,这个我会!!!另外,楼上上的兄弟,可否解释一下,您的代码??
      

  9.   

    BatchFile:TextFile;这个怎么用不起?????我的DELPHI老报错!!