原理
之所以可以使用批处理来实现文件自删除,是因为批处理有一个特别的地方就是:批处理提供了自己删除自己的命令:
del %0
这个命令,批处理执行完后,就会把自身文件删除了,而且不放进回收站。所以,有了这个关键技术作为前提,使用批处理方式实现程序的自删除,就好理解了。
- 构造自删除批处理文件,批处理文件的内容就是先延迟一定的时间,例如延迟 5 秒,然后开始删除指定文件后,再执行自删除命令
- 在程序中,创建一个新进程调用并批处理。进程创建成功后,立马结束进程
这样,进程创建起来,执行批处理文件。等批处理文件延迟结束,这是,程序进程也已经结束,便可以删除文件了。
编码实现
创建 choice 延时方式的批处理文件:
BOOL CreateChoiceBat(char *pszBatFileName)
{
int iTime = 5;
char szBat[MAX_PATH] = { 0 };
// 构造批处理内容
/*
@echo off
choice /t 5 /d y /n >nul
del *.exe
del %0
*/
::wsprintf(szBat, "@echo off\nchoice /t %d /d y /n >nul\ndel *.exe\ndel %%0\n", iTime);
// 生成批处理文件
FILE *fp = NULL;
fopen_s(&fp, pszBatFileName, "w+");
if (NULL == fp)
{
return FALSE;
}
fwrite(szBat, (1 + ::lstrlen(szBat)), 1, fp);
fclose(fp);
return TRUE;
}
创建 ping 延时方式的批处理文件:
BOOL CreatePingBat(char *pszBatFileName)
{
int iTime = 5;
char szBat[MAX_PATH] = {0};
// 构造批处理内容
/*
@echo off
ping 127.0.0.1 -n 5
del *.exe
del %0
*/
::wsprintf(szBat, "@echo off\nping 127.0.0.1 -n %d\ndel *.exe\ndel %%0\n", iTime);
// 生成批处理文件
FILE *fp = NULL;
fopen_s(&fp, pszBatFileName, "w+");
if (NULL == fp)
{
return FALSE;
}
fwrite(szBat, (1 + ::lstrlen(szBat)), 1, fp);
fclose(fp);
return TRUE;
}
创建进程调用批处理:
BOOL DelSelf(int iType)
{
BOOL bRet = FALSE;
char szCurrentDirectory[MAX_PATH] = {0};
char szBatFileName[MAX_PATH] = {0};
char szCmd[MAX_PATH] = {0};
// 获取当前程序所在目录
::GetModuleFileName(NULL, szCurrentDirectory, MAX_PATH);
char *p = strrchr(szCurrentDirectory, '\\');
p[0] = '\0';
// 构造批处理文件路径
::wsprintf(szBatFileName, "%s\\temp.bat", szCurrentDirectory);
// 构造调用执行批处理的 CMD 命令行
::wsprintf(szCmd, "cmd /c call \"%s\"", szBatFileName);
// 创建自删除的批处理文件
if (0 == iType)
{
// choice 方式
bRet = CreateChoiceBat(szBatFileName);
}
else if (1 == iType)
{
// ping 方式
bRet = CreatePingBat(szBatFileName);
}
// 创建新的进程, 以隐藏控制台的方式执行批处理
if (bRet)
{
STARTUPINFO si = { 0 };
PROCESS_INFORMATION pi;
si.cb = sizeof(si);
//指定wShowWindow成员有效
si.dwFlags = STARTF_USESHOWWINDOW;
//此成员设为TRUE的话则显示新建进程的主窗口
si.wShowWindow = FALSE;
BOOL bRet = CreateProcess(
//不在此指定可执行文件的文件名
NULL,
//命令行参数
szCmd,
//默认进程安全性
NULL,
//默认进程安全性
NULL,
//指定当前进程内句柄不可以被子进程继承
FALSE,
//为新进程创建一个新的控制台窗口
CREATE_NEW_CONSOLE,
//使用本进程的环境变量
NULL,
//使用本进程的驱动器和目录
NULL,
&si,
&pi);
if (bRet)
{
//不使用的句柄最好关掉
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
// 结束进程
exit(0);
::ExitProcess(NULL);
}
}
return bRet;
}
main 函数;
int _tmain(int argc, _TCHAR* argv[])
{
// 程序自删除
BOOL bRet = DelSelf( 0 );
if (FALSE == bRet)
{
printf("Selft Delete Error!\n");
}
else
{
printf("Selft Delete OK!\n");
}
system("pause");
return 0;
}