有时候,我们需要创建一个运行后能够自己删除自己的可执行程序即自删除文件。很明显如果一个进程通过直接调用DeleteFile()来删除自己是不可能的。必须另想办法,经过本人在网上参考很多资料后实际测试并集众家之所长,发现有二种方法效果比较好。现在将其封装成函数,这样使用将更加容易:
方法1,调用BAT文件。
//向指定文件写入文本。如果文件不存在就创建。
int WriteTextToFile(const char szFileName[], const char *lpszText)
{
FILE *pfile = fopen(szFileName, "w+");
if (pfile == NULL)
return -1;
int nWriteByte = fprintf(pfile, lpszText);
fclose(pfile);
return nWriteByte;
}
void DeleteApplicationSelf()
{
const char szFileName[] = "DeleteBat.bat"; //使用批处理
const char szDeleteBatText[] = "@ echo off\r\ndel %%1\r\ndel %%0";
//创建BAT文件并写入内容
WriteTextToFile(szFileName, szDeleteBatText);
//设置本程序进程基本为实时执行,快速退出。
SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
//通知资源管理器不显示本程序,当然如果程序没有真正的删除,刷新资源管理器后仍会显示出来的。
SHChangeNotify(SHCNE_DELETE, SHCNF_PATH, _pgmptr, NULL);
//运行bat文件来删除程序
ShellExecute(NULL, "open", "DeleteBat.bat", _pgmptr, NULL, SW_HIDE);
ExitProcess(0);
}
调用起来非常方便:直接一个DeleteApplicationSelf()就完成了任务。
方法二。调用系统的cmd程序并传入参数。
void DeleteApplicationSelf()
{
char szCommandLine[MAX_PATH + 10];
//设置本进程为实时执行,快速退出。
SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
//通知资源管理器不显示本程序,当然如果程序没有真正的删除,刷新资源管理器后仍会显示出来的。
SHChangeNotify(SHCNE_DELETE, SHCNF_PATH, _pgmptr, NULL);
//调用cmd传入参数以删除自己
sprintf(szCommandLine, "/c del /q %s", _pgmptr);
ShellExecute(NULL, "open", "cmd.exe", szCommandLine, NULL, SW_HIDE);
ExitProcess(0);
}
调用方法与前面相同。
这二种方法都不会出现DOS程序窗口,完全达到了无影无踪的删除效果,更加不会出现有的程序自删除后仍显示程序图标,要刷新资源管理器后才发现程序被删除了。
再对代码作下讲解:
1._pgmptr 的定义为extern char * _pgmptr,stdlib.h文件对其说明为:points to the module (EXE) name。使用_pgmptr与使用GetModuleFileName(NULL, szExePath, MAX_PATH);来得到程序的路径是等效的。
2.ShellExecute()最后一个参数为SW_HIDE表示隐藏窗口。
3.DOS命令del的/q参数表示安静模式,这样删除文件时就不会出现要求用户确认的提示对话框了。
附:二种方法都要加入头文件及lib库
#include <windows.h>
#include <stdlib.h>
#include <shellapi.h>
#include <shlobj.h>
#pragma comment(lib, "shell32.lib")