并行执行batch file并从每个文件中获取退出代码

如何从单个batch file并行执行一组batch file,并从中获取退出代码。 当我使用启动它并行执行batch file(新cmd窗口),但不返回每个退出代码。 而使用调用,我可以得到退出代码,但batch file执行顺序发生。 我有以下代码:

ECHO ON setlocal EnableDelayedExpansion sqlcmd -S server_name -E -i select_code.sql >\path\output.txt for /f "skip=2 tokens=1-3 delims= " %%a in ('findstr /v /c:"-" \path\output.txt') do ( echo $$src=%%a>\path1\%%c.prm echo $$trg=%%b>>\path1\%%c.prm set param_name=%%c start cmd \k \path\exec_pmcmd_ctrm.bat workflow_name %%param_name%% ping 1.1.1.1 -n 1 -w 5000 > nul set exitcode="%V_EXITCODE%" echo %exitcode%>>\path\exitcode.txt ) 

这与exec_pmcmd_ctrm.bat并行执行3次不同的variables,但是我无法从每个执行中获得退出代码。 我尝试使用通话,但是我错过了bat文件的并行执行。 在这方面有什么帮助?

Solutions Collecting From Web of "并行执行batch file并从每个文件中获取退出代码"

首先,通过%ERRORLEVEL%变量(而不是%V_EXITCODE% )从另一个批处理文件(以exit /B value命令结束)的“退出代码”。 而且,如果这个值 FOR循环内部改变,则必须通过延迟扩展来取代: !ERRORLEVEL! (在程序开始时启用EnableDelayedExpansion)。 不过,这些问题并不能解决你的问题,因为这里有一个误解。

当使用START命令(没有/ WAIT开关)时, 并行 cmd.exe进程开始执行。 这意味着没有一个直接的方法 ,即第一个批处理文件可以知道并行批处理在哪一刻结束,以便获得它的ERRORLEVEL! 没有“等待启动的批处理文件”命令,但即使存在,也不能解决有多个并发批处理文件的问题。 换句话说,你的问题不能通过直接的命令解决,所以解决方法是必要的。

最简单的解决方案是并行批处理文件将它们的ERRORLEVEL值存储在一个文件中,稍后可以通过原始批处理文件读取它们。 这意味着一个同步问题,以避免同时写入同一个文件,但这是另一回事…

这是一个纯粹的批处理文件解决方案。 基本上,这个脚本同时执行位于同一目录下的所有批处理文件,其中每个文件的退出代码( ErrorLevel )被写入到一个单独的日志文件(与批处理文件和扩展名.log ); 这些文件被检查存在; 一旦找到这样的日志文件,读取存储的退出代码,并将其与相应的批处理文件名称一起复制到汇总日志文件中; 只要所有的日志文件都被处理完了,这个脚本就会被终止。 所以这是代码 – 请参阅所有解释性对象:

 @echo off setlocal EnableExtensions DisableDelayedExpansion rem // Collect available scripts in an array: set /A "INDEX=0" for %%J in ("%~dp0*.bat" "%~dp0*.cmd") do ( if /I not "%%~nxJ"=="%~nx0" ( set "ITEM=%%~fJ" call set "$BATCH[%%INDEX%%]=%%ITEM%%" set /A "INDEX+=1" ) ) rem // Execute scripts simultaneously, write exit codes to individual log files: for /F "tokens=1,* delims==" %%I in ('set $BATCH[') do ( start "" /MIN cmd /C rem/ ^& "%%~fJ" ^& ^> "%%~dpnJ.log" call echo ^^%%ErrorLevel^^%% ) rem // Deplete summary log file: > "%~dpn0.log" rem/ rem // Polling loop to check whether individual log files are available: :POLLING rem // Give processor some idle time: > nul timeout /T 1 /NOBREAK rem /* Loop through all available array elements; for every accomplished script, rem so its log file is availabe, the related array element becomes deleted, rem so finally, there should not be any more array elements defined: */ for /F "tokens=1,* delims==" %%I in ('set $BATCH[') do ( rem // Suppress error message in case log file is not yet available: 2> nul ( rem // Read exid code from log file: set "ERRLEV=" & set "FILE=" < "%%~dpnJ.log" set /P ERRLEV="" if defined ERRLEV ( rem // Copd the read exit code to the summary log file: set "NAME=%%~nxJ" >> "%~dpn0.log" call echo(%%ERRLEV%% "%%NAME%%" rem // Undefine related array element: set "%%I=" rem // Store log file path for later deletion: set "FILE=%%~dpnJ.log" ) rem // Delete individual log file finally: if defined FILE call del "%%FILE%%" ) ) rem // Jump to polling loop in case there are still array elements: > nul 2>&1 set $BATCH[ && goto :POLLING endlocal exit /B 

这种方法与我在以下使用start子命令循环的改进批处理文件中使用的方法非常相似,但是在那里收集了同时执行的命令的输出。