我正在尝试让commit-build.bat执行其他.bat文件,作为构建过程的一部分。
commit-build.bat的内容:
"msbuild.bat"
"unit-tests.bat"
"deploy.bat"
这看起来很简单,但commit-build.bat只执行列表中的第一项(msbuild.bat)。
我分别运行了每个文件,没有任何问题。
我正在尝试让commit-build.bat执行其他.bat文件,作为构建过程的一部分。
commit-build.bat的内容:
"msbuild.bat"
"unit-tests.bat"
"deploy.bat"
这看起来很简单,但commit-build.bat只执行列表中的第一项(msbuild.bat)。
我分别运行了每个文件,没有任何问题。
当前回答
您的脚本应为:
start "msbuild.bat"
start "unit-tests.bat"
start "deploy.bat"
其他回答
我知道我参加晚会有点晚了,但这里有另一种方法。也就是说,这个方法应该等到第一个完成,第二个完成,依此类推。
start "" /wait cmd.exe /c msbuild.bat
start "" /wait cmd.exe /c unit-tests.bat
start "" /wait cmd.exe /c deploy.bat
使用此方法可能产生的唯一问题是,在生成新的cmd.exe实例时,每个cmd.exe实例中都保留了错误级别检查。
Or..
start "" /wait call msbuild.bat
start "" /wait call unit-tests.bat
start "" /wait call deploy.bat
希望这有帮助。
使用“&”
正如您注意到的那样,在没有CALL、START、CMD/C的情况下直接执行bat会导致输入并执行第一个文件,然后在第一个文件完成时停止进程。尽管您仍然可以使用&,这将与直接在控制台中使用command1&command2相同:
(
first.bat
)&(
second.bat
)& (
third.bat
)&(
echo other commands
)
就机器资源而言,这将是最有效的方法,尽管在最后一个块中,您将无法使用命令行GOTO、SHIFT、SETLOCAL。。并且其功能将与在命令提示符中执行命令几乎相同。在最后一个结束括号之后,您将无法执行其他命令
使用CALL
call first.bat
call second.bat
call third.bat
在大多数情况下,这将是最好的方法——它不创建单独的过程,但具有与调用:label作为子例程几乎相同的行为。在MS术语中,它创建一个新的“批处理文件上下文,并将控制权传递给指定标签之后的语句。第一次遇到批处理文件的结尾时(即,跳转到标签之后),控制权返回到调用语句之后的语句”
您可以使用在被调用文件中设置的变量(如果它们未在SETLOCAL块中设置),则可以直接访问被调用文件的标签。
CMD/C,管道,FOR/F
其他本机选项是使用CMD/C(/C开关将强制被调用的控制台退出并返回控制)cmd.exe在对bat文件使用FOR/F或使用管道时以非透明方式执行的操作。这将产生一个子进程,该子进程将具有调用蝙蝠的所有环境。在资源方面效率较低,但由于进程是独立的,解析崩溃或调用EXIT命令不会停止调用。bat
@echo off
CMD /c first.bat
CMD /C second.bat
::not so different than the above lines.
:: MORE,FINDSTR,FIND command will be able to read the piped data
:: passed from the left side
break|third.bat
启动
允许您更灵活地在单独的窗口中启动脚本,不必等待脚本完成,设置标题等。默认情况下,它使用cmd/K启动.bat和.cmd脚本,这意味着派生的脚本不会自动关闭。再次将所有环境传递给已启动的脚本,并消耗比cmd/c更多的资源:
:: will be executed in the same console window and will wait to finish
start "" /b /w cmd /c first.bat
::will start in a separate console window and WONT wait to be finished
:: the second console window wont close automatically so second.bat might need explicit exit command
start "" second.bat
::Will start it in a separate window ,but will wait to finish
:: closing the second window will cause Y/N prompt
:: in the original window
start "" /w third.cmd
::will start it in the same console window
:: but wont wait to finish. May lead to a little bit confusing output
start "" /b cmd /c fourth.bat
WMIC
与从现在开始的其他方法不同,示例将使用CMD.exe实用程序的外部(默认情况下在Windows上仍然可用)。WMIC实用程序将创建完全独立的过程,所以您不能直接等待完成。虽然WMIC的最佳特性是它返回派生进程的id:
:: will create a separate process with cmd.exe /c
WMIC process call create "%cd%\first.bat","%cd%"
::you can get the PID and monitoring it with other tools
for /f "tokens=2 delims=;= " %%# in ('WMIC process call create "%cd%\second.bat"^,"%cd%" ^|find "ProcessId"') do (
set "PID=%%#"
)
echo %PID%
您还可以使用它在远程计算机上启动进程,使用不同的用户等等。
SCHTASKS公司
使用SCHTASKS提供了一些功能,如(明显的)调度、以另一个用户(甚至是系统用户)的身份运行、远程机器启动等。再次在完全独立的环境(即它自己的变量)中启动它,甚至是隐藏的进程、带有命令参数的xml文件等:
SCHTASKS /create /tn BatRunner /tr "%cd%\first.bat" /sc ONCE /sd 01/01/1910 /st 00:00
SCHTASKS /Run /TN BatRunner
SCHTASKS /Delete /TN BatRunner /F
这里,也可以从事件日志中获取PID。
脚本运行程序
在启动脚本之间提供一些超时。基本事务功能(即错误回滚)和参数可以放在单独的XML文件中。
::if the script is not finished after 15 seconds (i.e. ends with pause) it will be killed
ScriptRunner.exe -appvscript %cd%\first.bat -appvscriptrunnerparameters -wait -timeout=15
::will wait or the first called script before to start the second
:: if any of the scripts exit with errorcode different than 0 will try
:: try to restore the system in the original state
ScriptRunner.exe -appvscript second.cmd arg1 arg2 -appvscriptrunnerparameters -wait -rollbackonerror -appvscript third.bat -appvscriptrunnerparameters -wait -timeout=30 -rollbackonerror
要在.bat文件中调用.bat文件,请使用
call foo.bat
(是的,这很愚蠢,如果您可以像在命令提示符下那样使用foo.bat调用它,这会更有意义,但正确的方法是使用call。)
有了正确的引用(有时可能很棘手):
start "" /D "C:\Program Files\ProgramToLaunch" "cmd.exe" "/c call ""C:\Program Files\ProgramToLaunch\programname.bat"""
第一个参数-标题(在本例中为空)第二个参数-/D指定起始目录,如果需要当前工作目录(例如“%~dp0”),则可以提交第三个参数-要启动的命令,“cmd.exe”第四个arg-命令的参数,其中的参数使用双引号(这是批量转义引号的方法)
所有其他答案都是正确的:使用call。例如:
call "msbuild.bat"
历史
在古老的DOS版本中,不可能递归地执行批处理文件。然后引入了调用命令,该命令调用另一个cmd shell来执行批处理文件,并在完成后将执行返回给调用cmd shell。
显然,在以后的版本中,不再需要其他cmd shell。
在早期,许多批处理文件依赖于这样一个事实,即调用批处理文件将不会返回到调用的批处理文件。在没有附加语法的情况下改变这种行为会破坏许多系统,如批处理菜单系统(使用批处理文件作为菜单结构)。
与微软的许多情况一样,向后兼容是导致这种行为的原因。
Tips
如果批处理文件的名称中有空格,请在名称两边使用引号:
call "unit tests.bat"
顺便说一句:如果您没有批处理文件的所有名称,也可以使用for来执行此操作(它不能保证批处理文件调用的顺序正确;它遵循文件系统的顺序):
FOR %x IN (*.bat) DO call "%x"
您还可以在通话后对错误级别做出反应。使用:
exit /B 1 # Or any other integer value in 0..255
以返回错误级别。0表示正确执行。在调用批处理文件中,您可以使用
if errorlevel neq 0 <batch command>
如果您的Windows比NT4/2000/XP旧,请使用if errorlevel 1来捕获所有错误级别1及更高版本。
要控制批处理文件的流,需要执行以下操作:-(
if errorlevel 2 goto label2
if errorlevel 1 goto label1
...
:label1
...
:label2
...
正如其他人所指出的:看看构建系统来替换批处理文件。