编辑:我会尽量更清楚地说明我真正想要什么。
我有一些很长的批处理文件,我想按顺序运行,并且仅在前一个完成后才开始。
我正在尝试使用主批处理文件控制它
我希望他们在自己的窗口中启动每个窗口,该窗口在完成后保持打开状态,以便以后回顾
按数字顺序排列:
1.运行主批处理文件
2.打开新的CMD窗口
3.运行批处理文件 1
4.等待1完成
5.1 完成,保持窗口打开
6.打开另一个新的cmd窗口
7.运行批处理2 等
--原文留言 --
嗨,我有一个 Windows 批处理文件,需要按顺序运行其他 Windows 批处理文件并等待它们完成,然后再开始下一个。
像这样:
@echo off
setlocal EnableDelayedExpansion
SET RUN="C:first.bat"
start /wait cmd /c %RUN%
SET RUN="C:second.bat"
start /wait cmd /c %RUN%
例如,第一个和第二个只是回显以下内容:
@echo off
echo 1st
exit /b 0
当我运行它时,它会在新窗口中启动第一个脚本,并在完成后保持窗口打开,但要继续第二个脚本,我必须关闭新的cmd窗口。
如何在不关闭第一个.bat cmd 窗口的情况下使主批处理脚本启动第二个.bat?
谢谢
这是一个非常不寻常的要求
- 其他批处理文件不应由处理主批处理文件的
cmd.exe
实例处理,而应由其他cmd.exe
实例处理,以便将其输出放在不同的控制台窗口中,并且 - 完成批处理文件的处理后,保持彼此命令进程运行,以便能够在其控制台窗口中查看其输出,并且 等待主批处理文件的进一步处理,直到启动的单独命令进程
- 完成批处理文件的处理,但不要等待启动的其他命令进程终止。
Windows 命令处理器cmd.exe
不是为批处理文件的序列化多处理而设计的,批处理文件具有自身的多个实例,最终应继续运行。
但是,这里有三个批处理文件,它们证明了这是可能的,后面将解释一个缺点。
主.bat
@echo off & goto Main
:WaitForBatch
start "Run %~nx1" %ComSpec% /D /S /K "(%ComSpec% /D /C "%~1") & title Finished %~n1"
echo Waiting for finished execution of "%~nx1" ...
:CheckBatchRun
%WaitCommand% >nul
%SystemRoot%System32tasklist.exe /NH /FI "IMAGENAME eq cmd.exe" /V | %SystemRoot%System32find.exe /I "%~nx1" >nul
if errorlevel 1 goto :EOF
goto CheckBatchRun
:Main
setlocal EnableExtensions DisableDelayedExpansion
title Run %~nx0
if exist %SystemRoot%System32timeout.exe (
set "WaitCommand=%SystemRoot%System32timeout.exe /T 1"
) else (
set "WaitCommand=%SystemRoot%System32ping.exe 127.0.0.1 -n 2"
)
call :WaitForBatch "%~dp0First.bat"
call :WaitForBatch "%~dp0Second.bat"
title Finished %~n0
pause
endlocal
第一.bat
@echo off
dir %SystemRoot% /B /S
第二.bat
@echo off
dir %SystemRoot%*.exe
echo(
pause
Main.bat
的编码方式是期望First.bat
和Second.bat
与Main.bat
位于同一目录中,但其他批处理文件也可以位于不同的目录中。执行三个批处理文件时的当前目录可以是任何目录。
Main.bat
首先为自己设置执行环境,即:
- 命令回显模式关闭并
- 已启用命令扩展,并且
- 禁用延迟扩展。
cmd.exe
处理Main.bat
的控制台窗口的窗口标题被修改为在开头显示Run Main.bat
。
接下来确定命令超时是否可用,在这种情况下,此命令将在以后用于一秒的延迟(Windows Vista 和更高版本的 Windows 客户端版本),或者是否必须将命令PING用于一秒钟的延迟(Windows XP)。
然后第一次使用批处理文件调用子例程WaitForBatch
First.bat
。
子例程使用命令START在窗口标题Run First.bat
的新控制台窗口中启动另一个命令进程,同时忽略 Windows 默认不存在的AutoRun
注册表字符串值。
第二个cmd.exe
实例在执行完接下来使用其他参数指定的命令行后继续运行。第二个cmd.exe
的命令行需要再次执行第三个cmd.exe
,忽略AutoRun
注册表字符串值(如果存在)以执行使用完全限定文件名指定的批处理文件First.bat
。第三个cmd.exe
实例在完成批处理文件的处理时关闭自身。
第二个cmd.exe
现在将其控制台窗口的标题更改为Finished First
。重要的是,窗口标题中不再有批处理文件扩展名。
第一个cmd.exe
实例处理Main.bat
在成功启动第二个cmd.exe
后继续批处理文件处理。它使用该命令等待一秒钟,然后运行TASKLIST以输出所有正在运行的cmd.exe
进程,其中包含详细的信息,这些信息被重定向到命令FIND以搜索不区分大小写的批处理文件名First.bat
。
只要有一个cmd.exe
进程运行First.bat
,第一个cmd.exe
就会继续在循环中对子例程WaitForBatch
Main.bat
进行批处理文件,并跳转到CheckBatchRun
。否则,子例程将保留,Main.bat
的处理继续进行,WaitForBatch
的第二个CALL与Second.bat
.
最后,Main.bat
还将其窗口标题更改为Finished Main
,并提示用户在Windows资源管理器中双击此文件开始执行的情况下Main.bat
按任意键。
First.bat
需要很长时间才能完成,因为必须将数千个文件名输出到第二个cmd.exe
的控制台窗口中。可以单击标题为Run First.bat
的控制台窗口的X符号立即终止第二个和第三个cmd.exe
的执行,这会导致第一个cmd.exe
继续启动另外两个cmd.exe
来处理Second.bat
。
也可以通过按Ctrl+C并使用Y回答终止批处理作业的提示(在英语 Windows 上)来中断长时间运行的First.bat
,导致第三个cmd.exe
真正停止处理First.bat
和第二个cmd.exe
继续运行,显示First.bat
的输出并将其控制台窗口的窗口标题更改为Finished First
。这是通过首先cmd.exe
处理Main.bat
检测到的,并开始处理Second.bat
。
此解决方案的缺点是,在标题为Run First.bat
的控制台窗口中按Ctrl+C时,DIR输出所有文件名,现在按N(在英语 Windows 上)仍会导致批处理作业终止。我不是 100% 确定为什么会发生这种情况。我对这种行为只有一个假设。
要了解使用的命令及其工作原理,请打开命令提示符窗口,在其中执行以下命令,然后完整而仔细地阅读每个命令的显示帮助页面。
call /?
cmd /?
dir /?
echo /?
endlocal /?
find /?
goto /?
if /?
pause /?
ping /?
setlocal /?
start /?
tasklist /?
timeout /?
title /?
为每个辅助批次 2 使用早期命令(每行一行)构造主批次 1 窗口标题:
任务列表/FI"窗口标题均衡器<批处理>" |在某个地方查找 "cmd.exe"> NUL & GOTO批处理>
以上行的操作顺序相反 = 最后一批首先列出
然后:
- 启动主批次 1
- 需要时启动批次 2 并退出批次 1
- 批次 2 中的最后一个命令: 启动主批次 1 & cmd/k
- 根据需要重复