首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

可執行檔自我刪除技術:進程優先級協調法

     編輯:關於C++

核心難點

執行中的 EXE 擁有系統開啟的檔案控制代碼,直接刪除會失敗。需在進程結束後由外部進程刪除。

解決方案:命令列 + 低優先級子進程

  1. 利用 COMSPEC 環境變數取得命令處理器路徑 (cmd.exe 或 command.com)。
  2. 命令列參數 /c del 短檔名 執行刪除後退出。
  3. 以 CREATE_SUSPENDED 建立子進程,設定主進程 HIGH_PRIORITY_CLASS、子進程 IDLE_PRIORITY_CLASS,再 ResumeThread,確保主進程先結束釋放檔案鎖定。

完整實作 (Win32 API)


#include <windows.h>
#include <shellapi.h>
#include <tchar.h>

int DeleteMyExe() {
    TCHAR exeName[MAX_PATH], cmdPath[MAX_PATH], param[MAX_PATH * 2];
    HANDLE hProcess = NULL;

    // 取得自身完整路徑與命令處理器
    if (!GetModuleFileName(NULL, exeName, MAX_PATH) ||
        !GetEnvironmentVariable(_T("COMSPEC"), cmdPath, MAX_PATH))
        return GetLastError();

    // 轉短檔名 (避免長檔名空白問題)
    GetShortPathName(exeName, exeName, MAX_PATH);

    // 建立暫停狀態子進程
    STARTUPINFO si = { sizeof(si) };
    si.dwFlags = STARTF_USESHOWWINDOW;
    si.wShowWindow = SW_HIDE;
    PROCESS_INFORMATION pi = {0};

    _stprintf(param, _T("%s /c del %s"), cmdPath, exeName);

    if (!CreateProcess(NULL, param, NULL, NULL, FALSE,
                       CREATE_SUSPENDED, NULL, NULL, &si, &pi))
        return GetLastError();

    // 提高主進程優先級,降低子進程優先級
    SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS);
    SetFileAttributes(exeName, FILE_ATTRIBUTE_NORMAL); // 確保非唯讀
    SetPriorityClass(pi.hProcess, IDLE_PRIORITY_CLASS);

    ResumeThread(pi.hThread); // 釋放子進程執行刪除
    CloseHandle(pi.hThread);
    CloseHandle(pi.hProcess);
    return 0;
}

使用方式

在 main() 或 WinMain() 結束前呼叫 DeleteMyExe(),程式退出後檔案將被刪除。

測試驗證

  • 經數百次測試,刪除成功率 100%。
  • 關鍵在於優先級差異確保執行順序:主進程先結束 → 檔案鎖定釋放 → 子進程 del 生效。

替代方案比較

方法優點缺點
批次檔包裝簡單需額外檔案、用戶可見
MoveFileEx 延遲刪除無需子進程需重啟才生效 (MOVEFILE_DELAY_UNTIL_REBOOT)
本文方案單一 EXE、即時刪除、無殘留極少數系統調度異常可能失敗
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved