如何簡單實現可執行文件的自我刪除

可執行文件即 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命令。在程序最後結束處調用它,就可以簡單的實現程序的自刪除功能。

01.include < windows.h>
02.#include < shellapi.h>
03.#include < stdio.h>
04. 
05.int DeleteMyExe()
06.{
07.TCHAR tcsExename[MAX_PATH];
08.TCHAR tcsParam[MAX_PATH * 2];
09.TCHAR tcsCmd[MAX_PATH];
10.HANDLE hProcess = NULL;
11. 
12.// get exe filename and command shell program
13.if( 0 == GetModuleFileName(NULL, tcsExename, MAX_PATH)
14.||  0 == GetEnvironmentVariable(_T("COMSPEC"), tcsCmd, MAX_PATH))
15.FAILRET;
16. 
17.// get short filename for command shell program
18.if( 0 == GetShortPathName(tcsExename, tcsExename, MAX_PATH))
19.FAILRET;
20. 
21.// create a command process, set its priority, then start it.
22.STARTUPINFO si;
23.PROCESS_INFORMATION pi;
24. 
25.ZeroMemory( &si, sizeof(si) );
26.si.cb          = sizeof(si);
27.si.dwFlags     = STARTF_USESHOWWINDOW;
28.si.wShowWindow = SW_HIDE;
29.ZeroMemory( &pi, sizeof(pi) );
30. 
31._stprintf(tcsParam, _T("%s /c del %s"), tcsCmd, tcsExename);
32.if(!CreateProcess(NULL,
33.tcsParam,
34.NULL,
35.NULL,
36.FALSE,
37.CREATE_SUSPENDED,
38.NULL,
39.NULL,
40.&si,
41.&pi))
42.{
43.return GetLastError();
44.}
45. 
46.// heigthen priority of the current process
47.SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS);   
48. 
49.// set file attribute to normal
50.SetFileAttributes(tcsExename, FILE_ATTRIBUTE_NORMAL);
51. 
52.// depress priority of command process, then start it
53.SetPriorityClass(pi.hProcess, IDLE_PRIORITY_CLASS);
54.ResumeThread(pi.hThread);
55.return 0;
56.}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章