執行中的 EXE 擁有系統開啟的檔案控制代碼,直接刪除會失敗。需在進程結束後由外部進程刪除。
COMSPEC 環境變數取得命令處理器路徑 (cmd.exe 或 command.com)。/c del 短檔名 執行刪除後退出。CREATE_SUSPENDED 建立子進程,設定主進程 HIGH_PRIORITY_CLASS、子進程 IDLE_PRIORITY_CLASS,再 ResumeThread,確保主進程先結束釋放檔案鎖定。
#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(),程式退出後檔案將被刪除。
del 生效。| 方法 | 優點 | 缺點 |
|---|---|---|
| 批次檔包裝 | 簡單 | 需額外檔案、用戶可見 |
| MoveFileEx 延遲刪除 | 無需子進程 | 需重啟才生效 (MOVEFILE_DELAY_UNTIL_REBOOT) |
| 本文方案 | 單一 EXE、即時刪除、無殘留 | 極少數系統調度異常可能失敗 |