如何让 .BAT 文件在完成后自动删除?

39

如何让 .BAT 文件在完成后自我删除?我有一个简单的批处理文件,可以终止一个进程。我想让这个 .BAT 文件自我删除。


7
所以你想要一个不显示任何窗口、在完成任务后终止进程并自删除的批处理文件。只是出于好奇,为什么呢? - Martin Smith
7个回答

60

Merlyn Morgan-Graham的答案成功删除了正在运行的批处理脚本,但是会生成以下错误信息:“找不到批处理文件。”如果控制台窗口在脚本终止时关闭,则这不是问题,因为消息会闪过得非常快,没人能看到它。但是如果控制台在脚本终止后仍然保持打开状态,那么错误消息就非常不可取了。

John Faminella的想法是需要另一个进程来干净地删除批处理文件,以避免错误。安排一个任务也可以解决问题,但有一个更简单的方法:使用START在同一控制台中启动一个新的删除进程。这需要时间来初始化和执行,因此父脚本在删除发生之前有机会正常终止。

start /b "" cmd /c del "%~f0"&exit /b

更新 2015-07-16

我发现了另一种非常巧妙的方法来让批处理脚本删除自身而不生成任何错误消息。这种技术依赖于GOTO的一个新发现行为(由一些俄罗斯人发现),在http://www.dostips.com/forum/viewtopic.php?f=3&t=6491上用英语描述。

总之,(GOTO) 2>NUL的行为类似于EXIT /B,但它允许在调用者的上下文中执行连接的命令!

所以你只需要:

(goto) 2>nul & del "%~f0"

3
我喜欢你的第二个解决方案。第一个解决方案很可能会很好地工作,但我不确定如果“start”在当前批处理解释器完成之前完成其工作是否严格保证能够工作。我假设如果进程调度程序正常工作或系统没有承受重负,那么任何竞态条件很可能不是问题,所以这只是一个小问题。 - Merlyn Morgan-Graham
(通过“保证可行”,我是指保证避免出现错误信息) - Merlyn Morgan-Graham
1
@MerlynMorgan-Graham - 绝对是竞争条件,所以你在技术上是正确的。但是很难想象出时间顺序被颠倒的情况。尝试设计一个失败案例可能会是一个有趣的项目。 - dbenham
刚刚在一个由VBA生成的批处理文件中使用了代码:(goto) 2>nul & del "%~f0",完美地运行了,批处理文件被删除且没有出现错误信息。 - 5202456
有人知道在Windows 11上(goto)技巧是否仍然有效吗?在Windows 10上对我有效,但是从一个Windows 11用户那里得到了报告,提到了错误消息:“找不到批处理文件”。 - djvg
2
@djvg - 如果它不起作用,我会感到震惊。(goto) 技术只有在没有未完成的 CALL 子程序需要返回时才会退出批处理。如果存在未完成的 CALL,那么 (goto) 将退出子例程而不是批处理,并且无论 Windows 版本如何,您都将(应该)收到批处理文件未找到的消息。 - dbenham

38
@ECHO OFF
SETLOCAL

SET someOtherProgram=SomeOtherProgram.exe
TASKKILL /IM "%someOtherProgram%"

ECHO "This script will now self-destruct. Please ignore the next error message"
DEL "%~f0"

注意,DEL命令最好是批处理文件中打算执行的最后一件事情,否则你就会倒霉 :)

这将打印出一个丑陋的错误消息,但它是无意义的,并且这种方式代码稍微不那么混乱。如果你非常关心如何摆脱错误消息,请查看dbenham的答案以消除它。


1
你能稍微解释一下吗? someotherprogram.exe是什么,你在里面放了什么? - Ricardo Polo Jaramillo
@Richard:SomeOtherProgram.exe 可以更改为任何程序。例如,notepad.exe。这是将被终止的程序,而该程序所做的事情并不重要 - 此批处理文件并不关心。它只使用 TaskKill 来终止具有该 exe 名称的任务。这样清楚吗?如果是,请问您是否认为需要将其添加到答案中?如果不是,请详细说明您理解的哪些部分,哪些部分不理解。 - Merlyn Morgan-Graham
2
感谢@Merlyn的回答。是我的错,我没有仔细阅读问题。我在想为什么需要杀死一个进程才能删除一个批处理文件本身 :) - Ricardo Polo Jaramillo
6
批处理文件本身可以被成功删除,但会生成一个不好看的“无法找到批处理文件”的错误信息。请参考我的回答中的方法来避免出现错误。 - dbenham
你可以通过将 ECHO ..DEL .. 替换为 DEL "%~f0" & EXIT 来避免看到消息“找不到批处理文件”。 - Branko
@Branko - 是的,那个方法可以实现,但它也会终止命令会话,并通常会关闭控制台。我的目标是创建一个解决方案,以保留命令会话和控制台。del "%~f0" & exit 有用的一种情况是如果自删除批处理文件是通过 cmd /c selfDeletingBatch.bat 启动的。这将保留控制台,并且不会打印错误消息。 - dbenham

4
如果您使用的是Windows XP Professional,并且具有适当的权限,您可以让批处理文件安排一次性的Windows计划任务以在稍后删除文件。请使用“schtasks”命令,该命令在此处记录:这里
否则,通常无法删除正在执行的文件,因为这可能会导致各种问题。此外,试图删除正在使用的可执行文件被视为非常可疑的行为,任何数量的防病毒程序都可能会阻止您这样做。

4
实际上,有一种令批处理文件自我删除且不会出错的方法,而且不需要特殊权限。请参见我的回答 - dbenham

1
你可以使用@Merlyn的答案。
@ECHO OFF
SETLOCAL
SET someOtherProgram=SomeOtherProgram.exe
TASKKILL /IM "%someOtherProgram%"
DEL "%~f0"

现在使用这个代码创建一个vbscript并将其保存为hidden.vbs,该vbscript将隐藏批处理文件的窗口。
set w = CreateObject(“WScript.Shell”)
W.Run chr(34) & “%userprofile%\desktop\the_batch_file.bat” & chr(34), 0
set w= Nothing

然后让批处理文件运行这个vbscript。
@ECHO OFF
SETLOCAL
SET someOtherProgram=SomeOtherProgram.exe
TASKKILL /IM "%someOtherProgram%"
start "path to hidden.vbs"
DEL "%~f0"

这将在删除批处理文件之前隐藏它,使错误消息无法看到。

1
只需在批处理文件的最后一行添加此命令即可。
Del batch_file_name.bat

batch_file_name.bat 是你的批处理文件的名称。

祝好!


@Ricardo Polo 不行,因为进程被锁定了,所以除非PID被释放,否则文件将无法删除。我实际上认为这就是上面讨论的内容,但是*@Hani Ludin*似乎没有注意到这一点! - CriticalPoint
@CriticalPoint 看起来对于批处理文件并不是这样!它能够正常工作!只有在从控制台运行时,你会得到一个烦人的“无法找到批处理文件”的错误信息。 - ewerybody

1

内联下一个命令来执行“最后的事情”作为幽灵自己。它可以是退出命令或其他一些在退出之前执行的事情。

@echo off
del "%~f0" && echo All's done. I must exit! && pause > nul && exit

运行正常,没有显示错误信息,谢谢。 - MoonLight

0

你也可以将 DEL "%~f0" 的输出重定向到 NULL 输出,像这样...

@ECHO OFF
SETLOCAL
SET someOtherProgram=SomeOtherProgram.exe
TASKKILL /IM "%someOtherProgram%"
DEL "%~f0" > NUL

2
抱歉,但讨论中的错误信息并不是来自于 del 命令,而是因为解释器试图从已删除的文件中读取“下一个命令”。您的建议并不能解决这个问题。 - Stephan
当我这样运行时,没有收到任何错误信息,但没有这样做会出错。 - Chad Estes
2
对我来说,使用或不使用“> nul”没有任何区别。正如我所说:错误不是来自“del”,因此重定向“del”的输出是无济于事的(除此之外:要抑制错误,您必须重定向STDERR:“2>nul”-这也无济于事)。 - Stephan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接