我希望在Windows上执行时删除可执行文件。我不认为这会对程序造成任何伤害,因为可以通过从USB执行'.exe'然后删除它来完成同样的操作 - 这无论如何都不会影响进程。
我没有运气就尝试过最简单的方法:
extern wchar_t *pExePath;
DeleteFileW(pExePath);
然后我尝试使用原生API:
UNICODE_STRING name;
static wchar_t strdrvPrefis [] {L"\\??\\"};
static wchar_t strObjectName[MAX_PATH];
name.Length = (name.MaximumLength = wcslen(pExePath) * sizeof(wchar_t) + (sizeof(strdrvPrefis) - sizeof(wchar_t)));
name.Buffer = strObjectName;
OBJECT_ATTRIBUTES objFile{};
objFile.Length = sizeof(OBJECT_ATTRIBUTES);
objFile.ObjectName = &name;
wcscat(strObjectName, strdrvPrefis);
wcscat(strObjectName, pExePath);
NtDeleteFile(&objFile);
如果我核心地退回,那么ACCES_DENIED会失败。
然后我尝试了'NtFsControlFile',但也没有成功:
HANDLE hFile;
IO_STATUS_BLOCK info;
NTSTATUS RetNt = NtOpenFile(&hFile, FILE_READ_DATA | FILE_WRITE_DATA, &objFile, &info, 0, FILE_NON_DIRECTORY_FILE | FILE_RANDOM_ACCESS | FILE_OPEN_REPARSE_POINT | FILE_NO_INTERMEDIATE_BUFFERING);
RetNt = NtFsControlFile(hFile, nullptr, nullptr, nullptr, &info, 0x000900A0 /*FSCTL_DELETE_OBJECT_ID*/, nullptr, 0, nullptr, 0);
NtClose(hFile);
现在上面的代码片段将在'NtOpenFile'失败。如果我从它的第二个参数中删除'FILE_WRITE_DATA',那么'NtFsControlFile'将因'STATUS_ACCESS_DENIED'而失败。
任何想法如何实现这一目标?
我正在使用VC ++ 2013。
答案 0 :(得分:2)
基本上,你不能这样做,因为当EXE运行时,进程打开文件。并且您无法删除进程已打开的文件。
正如您所注意到的,您可以通过USB记忆棒运行可执行文件,然后从USB端口拔出记忆棒。该计划继续运行。不过,我怀疑你可以做“安全删除驱动器”。
但那不会总是。 EXE不仅仅是代码。它包含可执行代码和资源,并且在EXE运行时并不是所有内容都被加载到内存中。例如,如果EXE包含大型位图资源,则在程序要求加载该资源之前,不会加载该资源。该过程保留了EXE的句柄,以便它可以根据需要加载资源。
因此,如果您的程序需要位于EXE中且尚未加载的资源,那么移除USB记忆棒会导致程序失败,如果它随后尝试加载其中一个资源。
据我所知,没有办法删除当前由另一个进程打开的文件。据我所知,你的程序无法关闭它对可执行文件的句柄。
文章http://www.catch22.net/tuts/self-deleting-executables(在重复的答案中链接)显示了一个示例,该示例创建了一个设置了delete-on-close标志的新文件。将可执行文件复制到该文件,然后执行该文件。然后删除原始可执行文件,当进程退出时,将自动删除您正在执行的可执行文件。这是我所知道的最好的方式来做你所要求的。
没有直接方式删除当前正在执行的文件。