我有一个简单的批处理文件,它运行并在运行后自行删除。该应用程序被放置在桌面上,并将使用注册表 RUNONCE 执行。要自行删除它,我使用下面的命令。
goto 2>nul & del /Q "%APP_PATH%"
与下面的命令不同,上面的命令不会在控制台中打印任何错误。
del /Q "%APP_PATH%"
桌面上的批处理文件被删除。当我们安装内部应用程序(不是恢复应用程序)时,使用
DEL
命令删除的批处理文件将恢复到之前的位置。我还没有机会检查内部应用程序源代码。通过这一级别的信息,有人知道为什么会发生这种奇怪的行为吗?
Windows 命令处理器
cmd.exe
逐行处理批处理文件。这意味着它打开一个批处理文件,读取下一行,解析它,如果没有更多的行可读取,则关闭批处理文件。然后它在解析的行上执行命令。请参阅Windows 命令解释器 (CMD.EXE) 如何解析脚本?
如果此处存在严重语法,Windows 命令处理器将退出批处理文件的处理。此处使用此错误条件处理。
创建一个包含以下行的批处理文件:
@echo off
goto
echo Third line!
打开命令提示符并通过键入完整的限定文件名来运行此批处理文件,即驱动器+路径+名称+扩展名,用双引号引起来。
由于第二行缺少批次标签,
cmd.exe
输出以下错误消息。
没有为 GOTO 命令指定批处理标签。
第三行不再被
cmd.exe
执行,因为在执行第二行命令行后,批处理文件处理被退出,因为这个严重的语法错误,不清楚cmd.exe
在哪里继续批处理文件处理。
现在让我们看看命令行:
goto 2>nul & del /Q "%APP_PATH%"
这是一个命令行,一行中有两个命令,如我在 使用 Windows 批处理文件的单行多个命令中的回答所详细描述的。
第一个命令
goto
缺少批处理标签会导致退出批处理文件处理。在这种情况下,cmd.exe
输出的错误消息将通过2>nul
重定向到设备NUL以抑制它。但是带有已扩展环境变量 del /Q "%APP_PATH%"
的第二个命令 %APP_PATH%
已在命令队列中。因此,接下来会执行该命令。
然后
cmd.exe
甚至不会再次尝试打开批处理文件来读取第三行,因为无效的 goto
命令会导致退出批处理文件处理,在这种情况下,如果 %APP_PATH%
引用该名称,则批处理文件处理甚至不再存在批处理文件的。
顺便说一句:
APP_PATH
很奇怪,因为具有完整路径的文件名具有误导性的环境变量名称。
这是一个更好的例子:
首先创建一个名为
Test1.cmd
的批处理文件,其中包含以下行:
@echo off
echo %~nx0 is calling Test2.cmd.
call "%~dp0Test2.cmd"
echo %~nx0 is processed further.
创建第二个名为
Test2.cmd
的批处理文件,其中包含以下行:
@echo off
set "BatchFile=%~f0"
echo %~nx0 is deleting itself now.
goto 2>nul & del /A /F "%BatchFile%"
然后从命令提示符窗口中运行
Test1.cmd
。输出是:
Test1.cmd is calling Test2.cmd.
Test2.cmd is deleting itself now.
Test1.cmd is processed further.
可以看到,通过
Test2.cmd
处理cmd.exe
,Test2.cmd
删除了自身,并且没有显示任何错误消息。但在 Test1.cmd
删除自身后,Test2.cmd
的处理仍在继续。
选项
/Q
在删除单个文件时并不是真正必要的,并且该文件在运行命令时肯定存在。选项 /A
对于删除批处理文件很有用,即使它设置了隐藏属性,否则 del
不会删除它。即使设置了只读属性,选项 /F
对于删除批处理文件也很有用。
另一种命令方法是使用批处理文件中的最后一个命令行,该命令应自行删除命令行:
del /A /F "%~f0" & exit
但它有一个缺点,因为可以在使用以下行创建
Test2.cmd
时看到:
@echo off
echo %~nx0 is deleting itself now.
del /A /F "%~f0" & exit
从命令提示符窗口中运行
Test1.cmd
。批处理文件 Test2.cmd
会自行删除,但命令 exit
会导致退出通过打开命令提示符窗口并处理两个批处理文件而打开的 cmd.exe
。因此,Test1.cmd
不会进一步处理,并且控制台窗口会立即关闭。
在命令
/B
后附加选项exit
将导致不退出cmd.exe
,但由于找不到cmd.exe
,Test2.cmd
会输出两条错误消息。
因此,使用
goto 2>nul & del /A /F "%~f0"
是自我删除批处理文件的最佳实践示例。
顺便说一句:顺序或两个命令很重要。使用
del /A /F "%~f0" & goto 2>nul
会导致 cmd.exe
输出错误消息,因为在这种情况下,它会尝试再次打开已删除的批处理文件。