程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> 如何簡單實現可執行文件的自我刪除

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

編輯:關於C++

可執行文件即 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;
}

(全文完)

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved