Windows 通过start命令返回变量
我正在寻找一种从启动命令启动的批处理脚本中获取返回值的方法。让我解释一下: 我需要通过从主批处理脚本同时启动多个子批处理脚本来利用多处理,然后在完成时检索每个子批处理文件返回值 我在call命令中使用了return变量,这一点在下面得到了很好的解释。 该解决方案不允许多线程,因为子批处理脚本是一个接一个地运行的 使用start命令允许多个正在运行的批处理脚本,但不会将值返回到主脚本,因为start命令显然创建了一个全新的变量上下文 是否有人有从子脚本返回值到主脚本的解决方案/解决方法 以下是我需要的模型: mainScript.batWindows 通过start命令返回变量,windows,multithreading,batch-file,scope,Windows,Multithreading,Batch File,Scope,我正在寻找一种从启动命令启动的批处理脚本中获取返回值的方法。让我解释一下: 我需要通过从主批处理脚本同时启动多个子批处理脚本来利用多处理,然后在完成时检索每个子批处理文件返回值 我在call命令中使用了return变量,这一点在下面得到了很好的解释。 该解决方案不允许多线程,因为子批处理脚本是一个接一个地运行的 使用start命令允许多个正在运行的批处理脚本,但不会将值返回到主脚本,因为start命令显然创建了一个全新的变量上下文 是否有人有从子脚本返回值到主脚本的解决方案/解决方法 以下是我需
@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
@echo off
setlocal
set "arg1=%~1"
set "retval1=%~1"
REM do some stuff...
REM return value
(endlocal
set "%retval1%=%foo%"
)
exit /b
订阅1.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
@echo off
setlocal
set "arg1=%~1"
set "retval1=%~1"
REM do some stuff...
REM return value
(endlocal
set "%retval1%=%foo%"
)
exit /b
除了将返回值写入文件之外,找不到任何替代方法,因此 main
@ECHO关闭
SETLOCAL
对于(12)个do中的%%a(
删除“%temp%\retval%%a”2>num
)
开始/分钟“q225220791.bat arg1 retval1
选项/t 1/d y>nul
开始/分钟“q225220791.bat arg1 retval2
:等待
选项/t 1/d y>nul
回显等待…%retval1%…%retval2%
如果不存在“%temp%\retval1”,则转到等待
如果不存在“%temp%\retval2”,则转到等待
对于(12)个do中的%%a(
对于/f“usebackqdelims=“%%i in”(“%temp%\retval%%a”)设置“retval%%a=%%i”
)
对于(12)个do中的%%a(
删除“%temp%\retval%%a”2>num
)
回显返回值为%retval1%%retval2%
后藤:EOF
q225220791.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
@echo off
setlocal
set "arg1=%~1"
set "retval1=%~1"
REM do some stuff...
REM return value
(endlocal
set "%retval1%=%foo%"
)
exit /b
@ECHO关闭
SETLOCAL
::随机等待2..10秒。
设置/a超时=%RANDOM%%%8+2
选项/t%超时%/d y>nul
::返回随机结果12..20
SET/a foo=%RANDOM%%%8+12
>%temp%\%2“回显%foo%
端部
出口
依赖子进程的第二个参数的值来设置临时文件名。我已经更改了批的名称以适应我的系统。不确定这是否可行,但只是测试以避免临时文件。所以为了在子进程中寻找一个可以从父进程读取的位置,我决定使用窗口标题 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
@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
master.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
@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
命令等待master。在XP中,这是不可用的,只需暂停即可替换,并且从master.cmd
必须修改等待循环,将processID标记包含在任务列表
处理中,以便使用taskkill
+1关闭等待任务,我正在写同样的答案:)除了我会使用SET/P来读取临时文件而不是FOR/F(抱歉,我来不及编辑我的第一条评论)非常感谢你们两位,FOR/F和SET/P都能完美地工作!出于好奇,这两者之间有什么区别?据我所知,即使是传递和解析多个变量,两者都会产生相同的结果。(对于一行,对于集合,每行一个变量)对于/f;它更详细,但允许处理多个输入行<代码>设置/p
更紧凑,但必须进行引导,以允许多个输入。在目前的情况下,没有实际的区别,因为您只处理一行。西红柿/西红柿。选择或风格的问题。