exe自删除(VC版本) 网上转载

我顶 字号:
 在开发程序过程中,有许多情况中都需要执行程序自己把自己从物理磁盘上删除,例如,卸装程序,一些黑客程序获取信息后自清除等,我们把这些具有自删除功能的程序统称为“自杀”程序。对于一名程序员,想必都有在程序中使用代码删除物理磁盘文件的经历吧,我们只需要简单的调用DeleteFile API函数就可以搞定,但是该函数并不能删除自己,当它执行删除自己时,将会导致出现“无法删除文件:拒绝访问。源文件可能正被使用”的错误提示,其原因是由于本程序在执行删除自己代码时仍处于内存中,在Windows中,不可以删除正在执行中的程序。 

    为了实现程序自删除功能,我们可以通过多进程的方法解决这个问题。可执行文件在结束返回前,创建一个运行命令窗口的新进程(在Windows98中为Command进程,在Windows2000/XP中为CMD进程),当然该命令窗口以隐藏方式执行,并通过传递参数执行删除功能。为了避免可执行文件的映像还在内存中就执行删除,需要把当前进程设置为实时优先级,而命令窗口进程设置为很低的IDLE优先级,这样首先可执行文件结束返回,再运行命令窗口的删除命令,就实现了该文件自身的删除功能。 

    下面我们就一起动手制作“自杀”(具有自删除功能)程序,程序在Visual C++6.0中开发编译。 

    首先,启动Visual C++6.0,新建一个MFC AppWizard(exe)类型的项目,项目名为SelfDelete,选择基于对话框模式创建程序框架。 

    接下来,打开资源编辑器,添加一个按钮控件,设置内容为开始“自杀”,如图一所示: 

    启动ClassWizard,为新添加的控件新建CLICK事件处理函数,再打开该函数,添加“自杀”代码如下: 

void CSelfDeleteDlg::OnButton1()   
{   
   // TODO: Add your control notification handler code here   
   SHELLEXECUTEINFO sei; 
   TCHAR szModule [MAX_PATH],szComspec[MAX_PATH],szParams [MAX_PATH]; 
   //获取文件路径名 
   if((GetModuleFileName(0,szModule,MAX_PATH)!=0) && 
        (GetShortPathName(szModule,szModule,MAX_PATH)!=0) && 
            (GetEnvironmentVariable("COMSPEC",szComspec,MAX_PATH)!=0)) 
   {  //设置命令行参数。 
      lstrcpy(szParams,"/c del "); 
      lstrcat(szParams, szModule); 
      lstrcat(szParams, " > nul"); 

      //初始化SHELLEXECUTEINFO结构成员 
      sei.cbSize = sizeof(sei); //设置类型大小。 
      //命令窗口进程句柄,ShellExecuteEx函数执行时设置。 
      sei.hwnd = 0; 
      sei.lpVerb = "Open";        //执行动作为“打开执行”。 
      sei.lpFile = szComspec;      //执行程序文件全路径名称。 
      sei.lpParameters = szParams; //执行参数。 
      sei.lpDirectory = 0; 
      //显示方式,此处使用隐藏方式阻止出现命令窗口界面。 
      sei.nShow = SW_HIDE; 
      //设置为SellExecuteEx函数结束后进程退出。 
      sei.fMask = SEE_MASK_NOCLOSEPROCESS; 
      //创建执行命令窗口进程。 
      if(ShellExecuteEx(&sei)) 
      {  //设置命令行进程的执行级别为空闲执行,这使本程序有足够的时间从内存中退出。   
         SetPriorityClass(sei.hProcess,IDLE_PRIORITY_CLASS); 
         //设置本程序进程的执行级别为实时执行,这本程序马上获取CPU执行权,快速退出。   
         SetPriorityClass(GetCurrentProcess(),REALTIME_PRIORITY_CLASS); 
         SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_TIME_CRITICAL);   
         //通知Windows资源浏览器,本程序文件已经被删除。 
         SHChangeNotify(SHCNE_DELETE,SHCNF_PATH,szModule,0); 
         //执行退出程序 
         EndDialog(0); 
       } 
   } 


    如果上面代码中的注释还不能帮助你理解代码的意义,请不要着急,后面我们还要对这些代码做详细的讲解。现在,你可以开始编译该程序项目,运行一下程序,请在Windows资源浏览器中仔细观察程序文件,当你按下“开始自杀”按钮后几秒,该程序文件从Windows资源浏览器中消失了,这也正在本程序想要得到的效果。 
    体验了“自杀”程序的神奇之后,让我们回过头来好好的分析一下实现“自杀”功能的代码。   
    前面我们已经谈过,实现“自杀”功能的核心是在程序中创建一个命令窗口新进程,通过向命令窗口进程传递del命令和参数来删除程序文件。命令窗口程序是由环境变量COMSPEC定义的,Win9x/ME使用COMMAND.COM,WinNT/2K/XP使用CMD.COM。程序把命令字符串“/c del filename > nul”传递给命令窗口,其中filename是需要删除文件的全路径文件名,文件名需要转换为8.3格式;/c开关用于命令窗口退出。   
    在实现代码中,首先就需要获取当前程序模块的全路径,并将其转化为命令窗口需要的8.3格式。代码中GetModuleFileName(0,szModule,MAX_PATH)函数实现了获取当前程序模式的全路径名称,并存放到变量szModule中。接着使用GetShortPathName(szModule,szModule,MAX_PATH)函数将szModule变量中的程序模块全路径名称转换成命令窗口需要的8.3格式。另外,还调用GetEnvironmentVariable("COMSPEC",szComspec,MAX_PATH)函数从系统环境变量COMSPC中获取了命令窗口程序的全路径。接下来,需要将存放在变量szModule中的具有8.3格式的程序模块全路径字符串组合成命令字符串“/c del ”+szModule+ “> nul”。   
    有了这些信息之后,就可以调用ShellExecuteEx() API函数创建一个新的命令窗口进程,该函数需要一个SHELLEXECUTEINFO类型的参数,调用ShellExecuteEx()函数必须需要初始化这个类型参数,有关SHELLEXECUTEINFO类型的详细说明请参阅MSDN。本处通过该参数将命令窗口进程的执行动作设为Open、执行文件为命令窗口(路径由szComspec提供)、执行文件参数为上面组合而成的命令字符串、显示方式为隐藏方式(隐藏方式可以阻止出现命令窗口界面)。   
    命令窗口通过调用ShellExecuteEx()函数以单独的进程运行,它的窗口句柄在SHELLEXECTUEINFO结构中的成员变量hProcess定义。自删除需要解决一个特殊的问题,即主程序必须在命令窗口删除它之前退出并关闭其打开的文件句柄。为了做到这一点,我们必须同步两个独立、并行的进程:当前程序进程和命令窗口进程。这可以通过操作CPU资源优先级来临时降低命令窗口的运行优先级别。这样,主程序将分配到CPU的所有资源直到其正常退出,而阻塞其它任何命令窗口的执行直到主程序结束。下面代码实现调整两个进程的执行优先级:   
    //设置命令行进程的执行级别为空闲执行,  
    //这使本程序有足够的时间从内存中退出。   
    SetPriorityClass(sei.hProcess,IDLE_PRIORITY_CLASS);   
    //设置本程序进程的执行级别为实时执行,  
    //这本程序马上获取CPU执行权,快速退出。   
    SetPriorityClass(GetCurrentProcess(),REALTIME_PRIORITY_CLASS);   
    SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_TIME_CRITICAL);   

    到此,自杀”功能基本实现。最后还需要做的事是调用SHChangeNotify(SHCNE_DELETE,SHCNF_PATH,szModule,0) 函数通知Windows资源浏览器已成功删除了程序文件。如果用户当前Windows资源浏览器窗口正处于程序文件目录的话,这个通知是非常必要的,它会导致Windows资源浏览器马上从程序文件目录列表中删除该程序文件项。做完了以上工作,一定要调用退出程序的代码,此处使用了EndDialog()函数,如果不及时退出程序的话,命令窗口进程就不能正常删除程序文件,其原因在前面我们已经研究过。   
    当你阅读完本文之后,一定与我有一个共同的感受:“自杀”也同样如此精彩!
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值