假设我有一个用于执行长时间构建的批处理文件,最后它会创建一个 EXE。如果我在开始构建之前忘记关闭应用程序,则链接阶段会在无法重新创建 EXE 时失败。
我想检查 EXE在构建开始时是否打开。我尝试将 EXE 文件重命名为自身,但尽管这给出了拒绝访问错误,但重命名命令(作为内部命令)没有设置 %ErrorLevel%。
检查将 %ErrorLevel% 设置为非零值的打开文件的非破坏性方法是什么?
假设我有一个用于执行长时间构建的批处理文件,最后它会创建一个 EXE。如果我在开始构建之前忘记关闭应用程序,则链接阶段会在无法重新创建 EXE 时失败。
我想检查 EXE在构建开始时是否打开。我尝试将 EXE 文件重命名为自身,但尽管这给出了拒绝访问错误,但重命名命令(作为内部命令)没有设置 %ErrorLevel%。
检查将 %ErrorLevel% 设置为非零值的打开文件的非破坏性方法是什么?
重命名方法对我不起作用(在 Windows XP SP3 上测试)。我启动了一个任意应用程序并尝试将其重命名为自身。没有错误,没有任何影响。
但是,这种方法确实有效:
COPY /B app.exe+NUL app.exe
当应用程序运行时,此命令产生了一条错误消息。并且当应用程序未使用时,该命令不仅保留了文件的内容,而且还保持修改时间戳不变。
因此,如果我是您,我可能会以这种方式使用此命令(如您所说,在批处理脚本的开头):
COPY /B app.exe+NUL app.exe >NUL || (GOTO :EOF)
如果前一个命令失败(提高了错误级别值) ,||
操作员会将控制权传递给它旁边的命令/块。因此,如果 COPY 失败,上述命令将终止脚本(如果文件打开,它将终止)。
错误消息将被保留(因为这些消息通常被发送到所谓的标准错误设备并且不会随着>NUL
重定向而被丢弃,而其他非错误消息通常被发送到标准输出,因此可以使用 来抑制>NUL
)和作为脚本提前终止的解释。但是,如果您想显示自己的消息,则可以尝试以下操作:
COPY /B app.exe+NUL app.exe >NUL 2>NUL || (ECHO Target file inaccessible& GOTO :EOF)
虽然>NUL
隐藏发送到标准输出的任何内容,2>NUL
但对标准错误执行相同操作。
找到了更好的方法:
:start
timeout /T 5
if exist %1 (
2>nul (
>> %1 (call )
) && (goto ende) || (goto start) ) else ( exit )
:ende
YourCode
这将每隔 5 秒检查一次“正在使用的文件”是否会重新启动。如果不是,它会变成你可以做下一个选项的地方
@echo off
:start
ren filename filename // rename file to same name
if errorlevel 1 goto errorline
echo command successfull file is not in use anymore
goto end
:errorline
echo Rename wasnt possible, file is in use try again in 5seconds
timeout /T 5
goto :start
:end
exit
将文件重命名为相同的名称,如果可能,脚本会跳转到 end 退出代码,否则会产生错误 code1 并跳转到 errorline,超时 5 秒后它会跳转到 :start 并且脚本从头开始。