请问大家 如何实现delphi 程序自删除 ,我看病毒、木马类就可以实现这种功能。请问那是怎么实现的?提供下代码学习下。谢谢!

解决方案 »

  1.   

    program del;
    uses
    windows;begin 
      WinExec(Pchar('cmd /c del ' + GetCommandLine),0); 
      ExitProcess(0);
    end.
      

  2.   

    {转自 http://topic.csdn.net/t/20020430/17/692138.html}procedure   TForm1.Button1Click(Sender:   TObject);
    var
      Selfname,BatFilename,s1,s2:string;
      BatchFile:   TextFile;
    begin
      Selfname:=Extractfilename(application.exename);//取EXE文件自己的名称
      BatFilename:=ExtractFilePath(Application.ExeName)+   'a.bat';//批处理文件名称
      S1:='@del   '+Selfname;
      S2:='if   exist   '+Selfname+'   goto   pp';
      assignfile(BatchFile,BatFilename);
      rewrite(BatchFile);
      writeln(BatchFile,':pp');
      writeln(BatchFile,S1);
      writeln(BatchFile,S2);
      writeln(BatchFile,'@del   %0');
      closefile(BatchFile);
      winexec(pchar(BatFilename),sw_hide);//隐藏窗口运行a.bat
      application.Terminate;//退出程序
    end;
      

  3.   

    procedure   TForm1.Button1Click(Sender:   TObject);
    var
      Selfname,BatFilename,s1,s2:string;
      BatchFile:   TextFile;
    begin
      Selfname:=Extractfilename(application.exename);//取EXE文件自己的名称
      BatFilename:=ExtractFilePath(Application.ExeName)+   'a.bat';//批处理文件名称
      S1:='@del   '+Selfname;
      S2:='if   exist   '+Selfname+'   goto   pp';
      assignfile(BatchFile,BatFilename);
      rewrite(BatchFile);
      writeln(BatchFile,':pp');
      writeln(BatchFile,S1);
      writeln(BatchFile,S2);
      writeln(BatchFile,'@del   %0');
      closefile(BatchFile);
      winexec(pchar(BatFilename),sw_hide);//隐藏窗口运行a.bat
      application.Terminate;//退出程序
    end;
    ------------------------------------------------------------------------
    这个我也试过,运行是可以删除应用程序本身,批处理也自删除。问题是我加载开机运行 就不能自删除。有没有不用批处理,效果更好的代码?等待中 。。
      

  4.   

    以前用C++写过,就几个API,楼主自己翻译一下吧.
    注意引用系统Shell方面的几单元.
    bool DeleteSelf()
    {
    SHELLEXECUTEINFO shi;
    TCHAR ptszModule[MAX_PATH] = {0};
    TCHAR ptszComspec[MAX_PATH] = {0};
    TCHAR ptszParams[MAX_PATH] = {0}; // 获取执行路径
    if ((0 != ::GetModuleFileName(0, ptszModule, MAX_PATH)) && 
    (0 != ::GetShortPathName(ptszModule, ptszModule, MAX_PATH)) && 
    (0 != ::GetEnvironmentVariable(_T("COMSPEC"), ptszComspec, MAX_PATH)))
    {
    // 设置参数
    _stprintf_s(ptszParams, MAX_PATH, _T("/c del /f /q \"%s\" > nul"), ptszModule); shi.cbSize = sizeof(shi);
    shi.hwnd = 0;
    shi.lpVerb = _T("open");
    shi.lpFile = ptszComspec;
    shi.lpParameters = ptszParams;
    shi.lpDirectory = 0;
    shi.nShow = SW_HIDE;
    shi.fMask = SEE_MASK_NOCLOSEPROCESS; // 调整程序进程和线程的优先级
    if ((0 == ::SetPriorityClass(::GetCurrentProcess(), REALTIME_PRIORITY_CLASS)) || 
    (0 == ::SetThreadPriority(::GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL)))
    {
    return false;
    } // 执行删除
    if (FALSE != ::ShellExecuteEx(&shi))
    {
    // 先通知程序退出
    ::PostQuitMessage(0); // 阻断 Command Shell 进程直到本程序退出
    ::SetPriorityClass(shi.hProcess, IDLE_PRIORITY_CLASS);
    ::SetProcessPriorityBoost(shi.hProcess, TRUE); // 向 Explorer Shell 通知删除消息
    ::SHChangeNotify(SHCNE_DELETE, SHCNF_PATH, ptszModule, 0); return true;
    }
    else // 如果删除失败则恢复程序进程和线程的优先级
    {
    ::SetPriorityClass(::GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
    ::SetThreadPriority(::GetCurrentThread(), THREAD_PRIORITY_NORMAL);
    }
    } return false;
    }
      

  5.   

    楼上的兄弟应该也采用了CMD命令完成吧?
      

  6.   

    在网上找了段代码如下:但运行不能自删除。 请高手指点,或给自认为好的CODE。谢谢!~1
    //////////////////////////////////////////////   
      procedure   DeleteSelf;   
      var   
          pExitProcess:   Pointer;   
          pDeleteFile:   Pointer;   
          pUnmapViewOfFile:   Pointer;   
          hModule:   THANDLE;   
          cBuf:array[0..MAX_PATH]of   Char;   
      begin   
          hModule   :=   GetModuleHandle('kernel32');   
          if   hModule   <>   0   then   
          begin   
              pExitProcess   :=   GetProcAddress(hModule,   'ExitProcess');   
              pDeleteFile   :=   GetProcAddress(hModule,   'DeleteFileA');   
              pUnmapViewOfFile   :=   GetProcAddress(hModule,   'UnmapViewOfFile');   
          end   else   
          begin   
              pExitProcess   :=   nil;   
              pDeleteFile   :=   nil;   
              pUnmapViewOfFile   :=   nil;   
          end;     
          hModule   :=   GetModuleHandle(nil);   
          GetModuleFileName(hModule,   cBuf,   Sizeof(cBuf));   
          CloseHandle(THANDLE(4));   
          asm   
              XOR   EAX,   EAX;   
              PUSH   EAX;   
              PUSH   EAX;   
              LEA   EAX,   cBuf;   
              PUSH   EAX;   
              MOV   EAX,   pExitProcess;         PUSH   EAX;         MOV   EAX,   hModule;         PUSH   EAX;         MOV   EAX,   pDeleteFile;   
              PUSH   EAX;   
              MOV   EAX,   pUnmapViewOfFile;   
              PUSH   EAX;   
              RET;   
          end;   
      end;   
        
      
      

  7.   

    是,是通过ShellExecuteEx来执行del命令进行删除的,效果很好的,试试吧.
      

  8.   

    我还是帮楼主把它翻译成Delphi的吧,放心用,效果不错.
    uses
      Windows,
      SysUtils,
      ShellAPI,
      ShlObj;{ 自杀 - 退出程序并删除自身. }
    function DeleteSelf: Boolean;
    var
      shi: SHELLEXECUTEINFO;
      pcModule: array [0..MAX_PATH] of Char;
      pcComspec: array [0..MAX_PATH] of Char;
      strParams: string;
    begin
      Result := False;  // 获取执行路径
      if (GetModuleFileName(0, pcModule, MAX_PATH) <> 0)
        and (GetShortPathName(pcModule, pcModule, MAX_PATH) <> 0)
        and (GetEnvironmentVariable('COMSPEC', pcComspec, MAX_PATH) <> 0) then
      begin
        strParams := Format('/c del /f /q "%s" > nul', [pcModule]);    shi.cbSize := SizeOf(shi);
        shi.Wnd := 0;
        shi.lpVerb := 'open';
        shi.lpFile := pcComspec;
        shi.lpParameters := PChar(strParams);
        shi.lpDirectory := nil;
        shi.nShow := SW_HIDE;
        shi.fMask := SEE_MASK_NOCLOSEPROCESS;    // 调整程序进程和线程的优先级
        if not SetPriorityClass(GetCurrentProcess, REALTIME_PRIORITY_CLASS)
          or not SetThreadPriority(GetCurrentThread, THREAD_PRIORITY_TIME_CRITICAL) then
        begin
          Exit;
        end;    // 执行删除
        if ShellExecuteEx(@shi) then
        begin
          // 先通知程序退出
          PostQuitMessage(0);      // 阻断 Command Shell 进程直到本程序退出
          SetPriorityClass(shi.hProcess, IDLE_PRIORITY_CLASS);
          SetProcessPriorityBoost(shi.hProcess, TRUE);      // 向 Explorer Shell 通知删除消息
          SHChangeNotify(SHCNE_DELETE, SHCNF_PATH, @pcModule, nil);      Result := True;
        end
        else
        begin
          // 如果删除失败则恢复程序进程和线程的优先级
          SetPriorityClass(GetCurrentProcess, NORMAL_PRIORITY_CLASS);
          SetThreadPriority(GetCurrentThread, THREAD_PRIORITY_NORMAL);
        end;
      end;
     end;
      

  9.   

    刚试过了,楼上的兄弟这个双击运行是可行的,不过没开机加载试。稍后我试下。不过这个楼上的兄弟有兴趣的话,可以帮助兄弟实现下,偶调试 不能自我删除。不知道怎么回事?
    ------------------------------------------------------------------------------------------
    转载:下面的代码由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不被删除.)