安装与卸载之卸载篇---程序自杀

来源:互联网 发布:php memcached 扩展 编辑:程序博客网 时间:2024/06/04 19:15
                        安装与卸载之卸载篇---程序自杀  
                                                                                                                陈经韬  
   
              电脑用得久了,安装的软件乱七八糟,怎么办?一般我们会打开控制面版里的添加删除程序选项,选择相应的卸载选项就可以了。但如果我们能在自己的程序中增加一个删除功能来实现"自杀",则会令软件增色不少。  
            有点电脑常识的人都知道,在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:   Lovejingtao@21.cn.com   
 
原创粉丝点击