自从开始实习就没有更新过blog了,加上软工、数据库、图形学乱七八糟的实验,有点忙不过来了。
本来一直在想以后做Linux相关的开发,周围认识的很多学长都走上了这条路,开始实习后却事与愿违搞起了Linux开发。其实说实话一直也不知道自己的兴趣点在哪里,工作了一个月后感觉可能还是桌面和互联网更适合自己,对于系统开发、运维这样的工作,干长时间可能会受不了……纠结啊
前两天和朋友聊到windows下一个程序如何删除自己,正好以前和同学讨论过这个问题,写出来凑个数。
其实真正的删除自己肯定是做不到的,至少用户态不行。windows下只要一个文件被某个进程打开就不能被删掉(Linux下可以删除任何打开的文件,只要有权限,而且一般不会影响程序的执行,因为文件系统会等到所有的打开的fd都释放后会才回收inode和data),所以一个windows进程在运行的时候是肯定不可以删除自己的可执行文件的,只能想一些旁门左道了。
Solution
方法其实很简单,就是在程序结束前开另一个进程去删自己,但是要求是自己删自己,所以只能借助系统utils。这时候就需要bat脚本来帮忙了。在CMD下删除一个文件很容易,一条del命令就搞定了,但是需要保证执行脚本的时候原进程已经结束运行了,一般来说用一条延时命令walk around“ping 127.0.0.1 -n 2”,2为秒数,然后用“&”连接del命令删除文件
ping 127.0.0.1 -n 2 >nul && del path/to/your/file.exe
更为保险的做法是在bat里用tasklist命令查看进程,循环直到找不到当前进程位置
原来的和同学讨论的是一个程序如何自己修改自己,做到单文件自动更新,实际上和自己删除自己是一个问题。无非就是先生成一个自身的副本,修改副本,再程序结束后用bat脚本覆盖自己就ok了,源代码如下
#include
#include
int main(int argc, char * argv[])
{
char self[_MAX_PATH];
char swap[_MAX_PATH];
// get the full path of myself
GetModuleFileName(NULL, self, _MAX_PATH);
// copy myself to a temp file for modify
strcpy(swap, self);
strcat(swap, ".tmp"); // add .tmp postfix. better to use tempnam()
CopyFile(self, swap, FALSE);
FILE * fp = fopen(swap, "ab");
// pending whatever you want to the exe
fwrite("Hack is not good, but i love it.", 32, 1, fp);
fclose(fp);
// "ping" is used for delay to wait the main process terminated.
// "move /Y src dst" : overide whtout warnning
// quotation marks are needed for paths which contain blank.
char bat[2*_MAX_PATH + 30] = "cmd /c ping 127.0.0.1 -n 2 >nul && move /Y "";
strcat(bat, swap);
strcat(bat, """);
strcat(bat, " "");
strcat(bat, self);
strcat(bat, """); // bat += "pathtoswap" "pathtoself"
WinExec(bat, SW_HIDE); // Exec the bat script with window hiden
return 0;
}
C库函数和win32 API混用,看着挺别扭,本来写的时候还想尝试一下匈牙利,被恶心到以后还是放弃了,还好用到的API都参数比较简单,自从大一的时候看到一个win32 API调用占了半屏后,对win32 API就深为恐惧,再加上满屏幕的大写,读起来简直就是噩梦…
Improvement
用ping命令延时只是一个walk around,在系统负载很重的情况下,2秒程序也未必退出了,所以应该寻找一个方法确定一个exe是否在运行。小研究了一下bat,发现通过tasklist命令和find命令可以搞定:
:loop
tasklist /NH | find /i "xxx.exe"
if %ERRORLEVEL% equ 1 (
goto loop
) else (
del pathtoyourfilexxx.exe
)
exit
ERRORLEVEL变量是上一条命令的返回值,不停的在进程列表里寻找xxx.exe直到找不到为止。
顺便bless一下灾区的同胞们还有但愿今天可以拿到工资….