安裝與卸載之卸載篇---程序自殺

                        安裝與卸載之卸載篇---程序自殺  
                                                                                                                陳經韜  
   
              電腦用得久了,安裝的軟件亂七八糟,怎麼辦?一般我們會打開控制面版裏的添加刪除程序選項,選擇相應的卸載選項就可以了。但如果我們能在自己的程序中增加一個刪除功能來實現"自殺",則會令軟件增色不少。  
            有點電腦常識的人都知道,在Windows下如果程序正在運行,那麼是無法將其刪除的,當然,也不是絕對不可以。CIH大家應該知道吧,它的核心有兩個,一個就是取得Ring0級權限,然後就可以隨便幹想幹的事(比如說修改正在運行的文件),而我們一般的程序是運行在Ring3級上的。順便提一句---NT下沒有Ring的概念,所以CIH對其無效。用Delphi內鑲彙編也可以取得Ring0級權限,但如果我們的程序運行在NT或者Win2000下就沒有效果了。在說句題外話,現在的編譯器都很不錯了,大多數程序員都編不出比編譯器編譯出的更理想的代碼,象Delphi,如果將它的某些單元代碼改用內鑲彙編,在某些方面如字符串處理方面會提高5倍左右的效率,但NT不支持某些彙編代碼,如果程序在NT下工作就會出錯,怎麼辦?穩定第一!所以我們不用這個方法,而且,用這個方法有點殺雞用牛刀的味道。  
        用過DOS的朋友應該還記得批處理文件吧,新建一個批處理文件a.bat,編輯其內容爲:del   %0,然後運行它,怎麼樣?a.bat把自己刪除掉了!!!好,我們就用它來進行程序的"自殺"!  
  找一個EXE可執行文件,比如說abc.exe,新建一個批處理文件a.bat,編輯其內容爲:  
  :pp  
  del   abc.exe  
  if   exist   abc.exe   goto   pp  
  del   %0  
  先運行abc.exe,再運行a.bat,然後將abc.exe退出,你會發現a.exe和a.bat都沒有了!!!按照這個思路,我們可以在程序中根據文件名稱寫一個批處理,將上面的abc.exe換成自己的EXE文件名就可以了。運行Delphi,新建一個工程,添加一個Button到窗體上,點擊Button,寫下如下代碼:  
   
  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;  
  那我們的事情是不是就完了?NO!上面的程序原理是對的,但如果你的程序是運行在系統目錄下如Windows目錄下或者Windows/System等目錄下,除非你打開那個目錄看着它刪除,否則根本沒法卸掉的。那怎麼辦?別急,我們請出一個函數CreateProcess,它的原型爲:  
  BOOL   CreateProcess(  
  LPCTSTR   lpApplicationName,   //   pointer   to   name   of   executable   module    
  LPTSTR   lpCommandLine,   //   pointer   to   command   line   string  
  LPSECURITY_ATTRIBUTES   lpProcessAttributes,   //   pointer   to   process   security   attributes    
  LPSECURITY_ATTRIBUTES   lpThreadAttributes,   //   pointer   to   thread   security   attributes    
  BOOL   bInheritHandles,   //   handle   inheritance   flag    
  DWORD   dwCreationFlags,   //   creation   flags    
  LPVOID   lpEnvironment,   //   pointer   to   new   environment   block    
  LPCTSTR   lpCurrentDirectory,   //   pointer   to   current   directory   name    
  LPSTARTUPINFO   lpStartupInfo,   //   pointer   to   STARTUPINFO    
  LPPROCESS_INFORMATION   lpProcessInformation   //   pointer   to   PROCESS_INFORMATION    
  );  
  這個函數和OpenProcess、ReadProcessMemory、WriteProcessMemory使用可以用來讀取和修改內存數據,常用的遊戲修改器就是用它。由於這些不是本文的重點所以這裏不作詳細介紹,感興趣的讀者可自行翻閱Delphi自帶的幫助文件。用CreateProcess函數創建一個進程就可以完美的完成我們的"程序自殺"了。  
  運行Delphi,新建一個工程,添加一個Button到窗體上,全部代碼如下:  
   
  unit   Unit1;  
   
  interface  
   
  uses  
  Windows,   Messages,   SysUtils,   Classes,   Graphics,   Controls,   Forms,   Dialogs,  
  StdCtrls;  
  type  
  TForm1   =   class(TForm)  
  Button1:   TButton;  
  procedure   My_DeleteMe;   //自定義程序自殺過程  
  procedure   Button1Click(Sender:   TObject);  
  private  
  {   Private   declarations   }  
  public  
  {   Public   declarations   }  
  end;  
   
  var  
  Form1:   TForm1;  
   
  implementation  
   
  {$R   *.DFM}  
   
  procedure   TForm1.Button1Click(Sender:   TObject);  
  begin  
  My_DeleteMe;  
  end;  
  procedure   TForm1.My_DeleteMe;   //程序自殺  
  //-----------------------------------------------------------   懷柔縣 襄樊市 連雲港市 宿遷市 淮陰市 六盤水市 江津市 婁底地區 南通市 紹興市 常州市 溫州市 鄂州市 邢臺市 河東區 河西區 巴彥淖爾 金昌市 紅橋區 塘沽區 內江市 東麗區 西青區 津南區 北辰區 怒江傈僳族自治州 寶坻縣 武清縣 林芝地區 盧灣區 安慶市 新鄉市 鶴壁市 安陽市 濮陽市 巢湖 其它地區
  function   GetShortName(sLongName:   string):   string;   //轉換長文件名  
  var  
  sShortName:   string;  
  nShortNameLen:   integer;  
  begin  
  SetLength(sShortName,   MAX_PATH);  
  nShortNameLen   :=   GetShortPathName(PChar(sLongName),  
  PChar(sShortName),   MAX_PATH   -   1);  
  if   (0   =   nShortNameLen)   then  
  begin  
  //   handle   errors...  
  end;  
  SetLength(sShortName,   nShortNameLen);  
  Result   :=   sShortName;  
  end;  
  //-------------------------------------------------  
  var  
  BatchFile:   TextFile;  
  BatchFileName:   string;  
  ProcessInfo:   TProcessInformation;  
  StartUpInfo:   TStartupInfo;  
  begin  
  BatchFileName   :=   ExtractFilePath(ParamStr(0))   +   '$$a$$.bat';  
  AssignFile(BatchFile,   BatchFileName);  
  Rewrite(BatchFile);  
  Writeln(BatchFile,   ':try');  
  Writeln(BatchFile,   'del   "'   +   GetShortName(ParamStr(0))   +   '"');  
  Writeln(BatchFile,   'if   exist   "'   +   GetShortName(ParamStr(0))   +   '"'   +   '   goto   try');  
  Writeln(BatchFile,   'del   %0');  
  Writeln(BatchFile,   'cls');  
  Writeln(BatchFile,   'exit');  
  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;  
  Application.Terminate;  
  end;  
  end.  
   
  補充:1、上面的批處理的   del   %0等同於   del   a.bat,用del   a.bat則批處理文件必須爲a.bat,用del   %0則可以隨意。  
  2、所有程序在Pwin98+Delphi5、Win2000+Delphi5下運行通過。  
  本文的標題爲《安裝與卸載之卸載篇》,下次將介紹如何用Delphi製作自己的安裝程序。記得有一位著名的黑客說過:我從來不去找什麼工具軟件,需要的話就自己寫一個。如果我們也持這種態度,則編程水平一定會越來越高。  
   
  ★作者:  
   
  陳經韜  
  Http:Lovejingtao.126.com    
  E-Mail:   [email protected]   
 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章