通过启动命令返回variables

我正在寻找一种方法来获得从启动命令启动的批处理脚本的值返回。 让我解释:

我需要通过从主批处理脚本同时启动多个子批处理脚本来利用多处理function,然后在完成时检索每个子batch file的返回值。

我一直在用call-command使用返回variables, dbenham很好地解释了这个问题 。 该解决scheme不允许multithreading,因为子批处理脚本一个接一个地运行。

使用start-command允许多个正在运行的批处理脚本,但是值不会返回到我的主脚本,因为显然start-command会创build一个全新的variables上下文。

有没有人有一个解决scheme/解决方法来从子脚本返回到主脚本的值?

下面是我需要的一个模型:

mainScript.bat

@echo off setlocal set "retval1=0" set "retval2=0" REM run two scripts in parallel: start "" subscript1.bat arg1 retval1 start "" subscript2.bat arg1 retval2 REM wait for returned value :waiting call :sleep 1 set /a "DONE=1" if %retval1% equ 0 set "DONE=0" if %retval2% equ 0 set "DONE=0" if %DONE% equ 0 goto :waiting echo returned values are %retval1% %retval2% exit /b 

subscript1.bat

 @echo off setlocal set "arg1=%~1" set "retval1=%~1" REM do some stuff... REM return value (endlocal set "%retval1%=%foo%" ) exit /b 

因此,看不到任何替代方法将返回值写入文件

主要

 @ECHO OFF SETLOCAL for %%a in (1 2) do ( del "%temp%\retval%%a" 2>nul ) start /min "" q225220791.bat arg1 retval1 choice /t 1 /dy >nul start /min "" q225220791.bat arg1 retval2 :waiting choice /t 1 /dy >nul ECHO wait...%retval1%...%retval2% if not exist "%temp%\retval1" goto waiting if not exist "%temp%\retval2" goto waiting for %%a in (1 2) do ( for /f "usebackqdelims=" %%i in ("%temp%\retval%%a") do set "retval%%a=%%i" ) for %%a in (1 2) do ( del "%temp%\retval%%a" 2>nul ) echo returned values are %retval1% %retval2% GOTO :EOF 

q225220791.bat

 @ECHO OFF SETLOCAL :: wait a random time 2..10 sec. SET /a timeout=%RANDOM% %% 8 + 2 choice /t %timeout% /dy >nul :: return a random result 12..20 SET /a foo=%RANDOM% %% 8 + 12 >"%temp%\%2" echo %foo% ENDLOCAL exit 

依靠第二个参数的值来设置子进程的临时文件名。 我已经改变了批次的名称,以适应我的系统。

不知道这是否是可行的,但只是测试,以避免临时文件。 所以寻找一个可以从父进程中获得的子进程的地方,我决定使用窗口标题。

task.cmd

 @echo off setlocal rem Retrieve task information and set window title set "taskID=%~1" title [task];%taskID%;working; rem Retrieve the rest of parameters. For this sample, a random value set /a "timeToWait=%~2 %% 30" rem Simulate command processing timeout /t %timeToWait% rem Calculate a return value for this task for /f "tokens=1-10 delims=,.:/ " %%a in ("%date%%time%_%~2") do set "returnValue=%%a%%b%%c%%d%%e%%f%%g%%h%%i%%j" rem Signal the end of the task title [task];%taskID%;ended; my return value is %returnValue% ; rem Wait for master to end this tasks cls echo Waiting for master.... waitfor %taskID% rem Cleanup endlocal 

master.cmd

 @echo off setlocal enableextensions enabledelayedexpansion rem Configure tasks set "taskPrefix=myTSK" set "numTasks=5" rem Start tasks for /l %%a in (1 1 %numTasks%) do ( set "return[%taskPrefix%%%a]=unknown" start "[task];%taskPrefix%%%a;working;" cmd /c "task.cmd %taskPrefix%%%a !random!" ) rem Wait for tasks to start timeout /t 2 > nul rem Wait for tasks to end. Get the list of cmd.exe windows with window title rem to see the state of the task rem Tasks in working state indicate master needs to keep working rem Tasks in ended state have the return value in the window title and are rem waiting for the master to retrieve the value and end them :wait set "keepWaiting=" for /f "tokens=9 delims=," %%a in ('tasklist /fi "imagename eq cmd.exe" /fo csv /v ^| findstr /l /c:"[task];%taskPrefix%"' ) do for /f "tokens=2-4 delims=;" %%b in ("%%a") do ( if "%%c"=="working" ( set "keepWaiting=1" ) else if "%%c"=="ended" ( set "return[%%b]=%%d" start "" /min waitfor.exe /si %%b ) ) rem If any task has been found in working state, keep waiting if defined keepWaiting ( echo %time% : waiting ... timeout /t 5 > nul goto wait ) rem All tasks have ended. Show return values for /l %%a in (1 1 %numTasks%) do ( echo task #%%a ended with exit value :[!return[%taskPrefix%%%a]!] ) endlocal 

在这个例子中,任务等待主人使用waitfor命令。 在XP中这是不可用的,可以用一个暂停来代替,并且从master.cmd ,等待循环必须被修改,以包含processID令牌在任务tasklist处理中,所以等待任务可以用taskkill关闭。