当前位置: 首页 > 图文教程 > 开发语言 > VC++ > 如何简单实现可执行文件的自我删除

VC++
在类VC的界面实现中加入目录树
软件换肤技术在 BCB 中的实现
利用非模窗口生成MDI介面
报表输出轻松搞定
Windows 中不规则窗体的编程实现
解说Win32的窗口子类化
使用测试优先方法开发用户界面
一个简单的登录对话框的实现
一个简单的日记本程序
从资源中加载皮肤
一个在RichEdit中添加表情图象的类
ActiveSkin 4.3 软件换肤在VC中的实现
一种另类“关于(About)”对话框的动态显示方法
对话框打印预览及打印
关于如何换肤、子类化的解决方案
制作 MSN、QQ 的消息提示窗口
如何对 BCGControlBarPro 进行换肤
定制个性化的对话框窗口类
改变窗口中的光标形状
更新MFC中的视图,跟踪.NET Framework中的事件

VC++ 中的 如何简单实现可执行文件的自我删除


出处:互联网   整理: 软晨网(RuanChen.com)   发布: 2009-10-30   浏览: 108 ::
收藏到网摘: n/a

如何简单实现可执行文件的自我删除

作者:zyq654321

可执行文件即 EXE 文件在运行过程中,由系统管理其打开的句柄。此时对该文件的一些操作是被系统禁止的,比如删除操作。然而在某些场合,可能须要程序有自我删除的功能,也就是程序运行结束后删除自身。基于这个想法,可以有一种很简单的方法来实现这个基本功能。

本方法基于两点来实现删除功能。一是利用 windows 的 command program 的删除文件操作;再者就是启动新的进程来执行这个删除操作。下面就仔细说明。

Windows 中的 command program 是一个系统的 shell program. 在 windows95/98/Me 中,其文件名为 command.com ,而在 NT/2000/XP 中则是 cmd.exe 。我们可以通过环境变量 COMSPEC 得到其全路径名。

假定目前我们所使用的是 XP ,在命令行中输入 :

cmd.exe /?

即得到 command shell 的使用方法;其中 /c 的含义是:执行字符串指定的命令然后终断,这正是我们所须要的。这样利用 command shell 删除一个文件的命令如下:

cmd.exe /c del mypro.exe

这里要注意一点,文件名应该是短文件名(文件名不得超过 8 个字符 , 后缀不超过 3 个字符)。如果实际文件是长文件句,那么程序中我们可以用 GetShortPathName 这个 API 函数来转换。

接下来我们要做是如何在一新的进程中成功的执行这一指令。起来一个新进程的命令主要有 ShellExecute 和 CreateProcess 。

先使用 ShellExecute 为例。在程序的结束处使用如下语句:

ShellExecute(NULL, "open","cmd.exe", "/c del mypro.exe ", NULL, SW_HIDE);

编译后运行文件发现执行成功,文件运行完后被删除。但是后面做多次实验后,发现有时文件执行完后并不会被删除。通过分析,认为在删除操作执行时,可执行文件还未关闭。也就是说只有在执行文件的进程关闭后,执行删除操作的进程才能完成操作。这样就有了一个问题,系统负责进程和线程的调度执行,我们无法人为规定进程或线程以某种秩序执行。

对此我的解决办法是,建立执行删除操作的进程时设定其为挂起状态,从而为其的设定一个低优先级别,同时提高执行文件的进程级别,然后才正式起动新进程。这样基本可以保证两个进程的先后执行。这样新的解决方法就是用CreateProcess以CREATE_SUSPEND标志来建立新进程,然后用SetPriorityClass来设定相应的优先级,主进程的优先级是HIGH_PRIORITY_CLASS,而执行删除操作的进程的优先级是IDLE_PRIORITY_CLASS。经过数百次的测试,删除操作都是成功的。

下面是一个封装了删除操作的函数,函数内起动一个进程执行command shell的del命令。在程序最后结束处调用它,就可以简单的实现程序的自删除功能。
#include <windows.h>#include <shellapi.h>#include <stdio.h>int DeleteMyExe(){	TCHAR tcsExename[MAX_PATH];	TCHAR tcsParam[MAX_PATH * 2];	TCHAR tcsCmd[MAX_PATH];	HANDLE hProcess = NULL;	// get exe filename and command shell program	if( 0 == GetModuleFileName(NULL, tcsExename, MAX_PATH)	|| 0 == GetEnvironmentVariable(_T("COMSPEC"), tcsCmd, MAX_PATH))	FAILRET;	// get short filename for command shell program	if( 0 == GetShortPathName(tcsExename, tcsExename, MAX_PATH))	FAILRET;	// create a command process, set its priority, then start it.	STARTUPINFO si;	PROCESS_INFORMATION pi;	ZeroMemory( &si, sizeof(si) );	si.cb = sizeof(si);	si.dwFlags = STARTF_USESHOWWINDOW;	si.wShowWindow = SW_HIDE;	ZeroMemory( &pi, sizeof(pi) );	_stprintf(tcsParam, _T("%s /c del %s"), tcsCmd, tcsExename);	if(!CreateProcess(NULL, tcsParam, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &si, &pi))	{	return GetLastError();	}	// heigthen priority of the current process	SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS);	// set file attribute to normal	SetFileAttributes(tcsExename, FILE_ATTRIBUTE_NORMAL);	// depress priority of command process, then start it	SetPriorityClass(pi.hProcess, IDLE_PRIORITY_CLASS);	ResumeThread(pi.hThread); return 0;}
(全文完)