本文介绍几种实现在程序退出后,从磁盘删除自身 exe 文件的方式。该技术通常应用于安装包卸载程序中。

一、借用 choice 命令实现

Windows 提供了 choice 命令,允许用户从选择列表选择一个项目并返回所选项目的索引。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
C:\Users\akx>choice /?

CHOICE [/C choices] [/N] [/CS] [/T timeout /D choice] [/M text]

描述:
该工具允许用户从选择列表选择一个项目并返回所选项目的索引。

参数列表:
/C choices 指定要创建的选项列表。默认列表是 "YN"

/N 在提示符中隐藏选项列表。提示前面的消息得到显示,
选项依旧处于启用状态。

/CS 允许选择分大小写的选项。在默认情况下,这个工具
是不分大小写的。

/T timeout 做出默认选择之前,暂停的秒数。可接受的值是从 0
到 9999。如果指定了 0,就不会有暂停,默认选项
会得到选择。

/D choice 在 nnnn 秒之后指定默认选项。字符必须在用 /C 选
项指定的一组选择中; 同时,必须用 /T 指定 nnnn。

/M text 指定提示之前要显示的消息。如果没有指定,工具只
显示提示。

示例:
CHOICE /?
CHOICE /C YNC /M "确认请按 Y,否请按 N,或者取消请按 C。"
CHOICE /T 10 /C ync /CS /D y
CHOICE /C ab /M "选项 1 请选择 a,选项 2 请选择 b。"
CHOICE /C ab /N /M "选项 1 请选择 a,选项 2 请选择 b。"

实现方式如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
bool DeleteSelf {
wchar_t szSystemDir[MAX_PATH] = {0};
if (GetSystemDirectoryW(szSystemDir, MAX_PATH) > 0) {
PathAddBackslashW(szSystemDir);
}

wchar_t szFullCmd[MAX_PATH] = {0};
StringCchPrintfW(szFullCmd, MAX_PATH, L"%scmd.exe /C choice /C Y /N /D Y /T 4 & rmdir \"%s\" /Q",
szSystemDir, szPath);

STARTUPINFOW si = {sizeof(STARTUPINFOW)};
PROCESS_INFORMATION pi;
if (CreateProcessW(NULL, szFullCmd, NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, szSystemDir, &si,
&pi)) {
if (pi.hThread)
CloseHandle(pi.hThread);
if (pi.hProcess)
CloseHandle(pi.hProcess);
return true;
}
return false;
}

int main() {
bool ret = DeleteSelf();
return 0;
}

二、使用计划任务实现

在程序退出前添加 Windows 计划任务,计划任务在程序退出几秒后执行删除文件的操作。

这种实现方式需要程序具有管理员权限。

此处省略具体的实现方式。