副标题#e#
可执行文件即 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。颠末数百次的测试,删除操纵都是乐成的 。
#p#副标题#e#
下面是一个封装了删除操纵的函数,函数内起动一个历程执行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;
}
(全文完)