2017年12月5日 星期二

[BCB][C++] 一個有趣的題目,執行過程中destory自己的資料夾

昨天開始就一直在積極尋找如何刪掉程式所在資料夾
如果開啟C:/app/a.exe
然後在執行中下達刪除C:/app
結果是資料夾內容會全部清空
但C:/app這個資料夾還在

so...
是不是更改呼叫外部的指令可以修正這問題?
WinExec、system、ShellExcute...
是不是可以直接叫bat檔?
是不是另外call 程式可以?

這個是在執行時把自己先複製到temp資料夾
再執行另一個process
目的是可以刪掉exe檔

#include <Windows.h>
#include <stdlib.h>
#include <tchar.h>
// remember: Put in WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
...
// Is this the original EXE ther Clone?
// The original EXE receives one argument,
// the clone more.
if (__argc == 1) {
// Original EXE: Start the Clone.
// Copy EXE to the temporary directory
TCHAR szPathOrig[_MAX_PATH], szPathClone[_MAX_PATH];
GetModuleFileName(NULL, szPathOrig, _MAX_PATH);
/*_MAX_PATH*/
GetTempPath(_MAX_PATH, szPathClone);
GetTempFileName(szPathClone, __TEXT("Del"), 0, szPathClone);
CopyFile(szPathOrig, szPathClone, FALSE);
// Open the Clone using FILE_FLAG_DELETE_ON_CLOSE
HANDLE hfile = CreateFile(szPathClone, 0, FILE_SHARE_READ,
NULL,OPEN_EXISTING,FILE_FLAG_DELETE_ON_CLOSE,0);
// Start the Clone. Pass the PID and the fully qualified path
// of the original file
TCHAR szCmdLine[512];
HANDLE hProcessOrig = OpenProcess(SYNCHRONIZE, TRUE,
GetCurrentProcessId());
wsprintf(szCmdLine, __TEXT("%s %d \"%s\""), szPathClone,
hProcessOrig, szPathOrig);
STARTUPINFO si;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
PROCESS_INFORMATION pi;
CreateProcess(NULL, szCmdLine, NULL, NULL, TRUE, 0,
NULL, NULL, &si, &pi);
CloseHandle(hProcessOrig);
CloseHandle(hfile);
return(0);
// now the original process may terminate
} else {
// Clone-EXE: Delete the original EXE after termination
HANDLE hProcessOrig = (HANDLE) atoi(__targv[1]);
WaitForSingleObject(hProcessOrig, INFINITE);
CloseHandle(hProcessOrig);
DeleteFile(__targv[2]);
}
...
view raw gistfile1.txt hosted with ❤ by GitHub


結果可以成功開起來
也確實可以刪掉當前資料夾中的exe
但是空資料夾還在

FILE *fp;
FILE *fp1;
char buf[MAX_PATH];
char filepath[MAX_PATH];
fp = fopen("c:\\a.bat", "w");
if(fp == NULL)
{
return ;
}
String Current_Dir,Target_Dir;
Current_Dir = GetCurrentDir();
sprintf(buf,"%s",Current_Dir);
sprintf(filepath, "\"%s\"", buf);
//fprintf(fp, "taskkill /f /im %s\n",__argv[0]);//full path
fprintf(fp, "taskkill /f /im Project_clone.exe\n");
fprintf(fp, "@ping 127.0.0.1 -n 3 -w 3000 > nul\n");
fprintf(fp, ":while1\n");
fprintf(fp, "rd %s /q /s \n", filepath);
//fprintf(fp, "if EXIST %s goto while1 \n", filepath);
fprintf(fp, "del \"c:\\a.bat\"\n");
fclose(fp);
view raw gistfile1.txt hosted with ❤ by GitHub

學到的cmd指令:
等同於用工作管理員刪除process
taskkill /f /im Project_clone.exe

等待三秒
@ping 127.0.0.1 -n 3 -w 3000 > nul

刪除資料夾以及裏頭的東西
rd C:/app /q /s

最後測試發現只要從程式call
不管用WinExec、system、ShellExcute另一個程式、bat
資料夾就是刪不掉
可能是directory path還在call heap裡
找很久找不到如何解除這個path
後來想到用常駐程式去摧毀
可是對方不要再有另一個service
要安裝很麻煩
我想到用工作排程

String s,sh;
sh=FormatDateTime("hh:mm", Now()+0.001);//+1 minute
s.sprintf("AT %s C:\\a.bat",sh);
Label1->Caption=s;
WinExec(s.c_str(),SW_HIDE);
view raw gistfile1.txt hosted with ❤ by GitHub


這樣就可以了

沒有留言:

張貼留言