我有两个脚本,foo和bar。 Foo叫吧。我需要在预先设定的时间内打印条形输出线,并从条形图中捕获%ERRORLEVEL%。我似乎无法弄清楚如何做到这两点。我进一步无法弄清楚如何准确显示时间条的执行行,只有时间条完成执行并将控制权转回foo。
foo.cmd
echo off
for /f "delims=" %%a in ('bar') do (call :log "%%a")
echo after loop error level: %ERRORLEVEL%
goto :eof
:log
echo during loop error level: %ERRORLEVEL%
echo [%time%]: %~1
goto :eof
bar.cmd
echo this is log output line 1
timeout /t 2 /nobreak > NUL
echo this is log output line 2
EXIT /B 3
此次运行的输出是:
>foo
>echo off
during loop error level: 0
during loop error level: 0
[13:24:22.21]: this is log output line 1
during loop error level: 0
during loop error level: 0
during loop error level: 0
[13:24:22.23]: this is log output line 2
during loop error level: 0
after loop error level: 0
我希望从这次运行中获得:
>foo
>echo off
during loop error level: 0
during loop error level: 0
[13:24:20.21]: this is log output line 1
during loop error level: 0
during loop error level: 0
during loop error level: 0
[13:24:22.23]: this is log output line 2 <------- this is 2 seconds later
during loop error level: 0
after loop error level: 3 <------ I got %ERRORLEVEL%
感谢任何帮助!
答案 0 :(得分:0)
main.cmd:
@echo off
setlocal
call bar 2> stderr.txt > stdout.txt
set "errorsaved=%errorlevel%"
for /f "delims=" %%A in (stdout.txt) do echo [%time%]: %%A
if %errorsaved% gtr 0 (
echo [%time%]: ERRORLEVEL: %errorsaved%
for /f "delims=" %%A in (stderr.txt) do echo [%time%]: ERRORINFO: %%A
)
del stderr.txt stdout.txt
bar.cmd:
@echo off
setlocal
echo some output
echo more output
>&2 echo %~nx0 failed to continue
exit /b 1
for
循环中的命令不想设置errorlevel
。
一个选项是将stdout和stderr保存到文件并保存errorlevel
到变量进行后期处理。
main.cmd
调用bar.cmd
并将流重定向到文件。
%errorlevel%
的值会保存到%errorsaved%
。
读取并回显文件stdout.txt
。
如果bar.cmd
设置errorlevel
大于0,则%errorsaved%
被回显,文件stderr.txt
被读取并回显。
最后删除文件。
测试输出:
[ 0:08:34.46]: some output
[ 0:08:34.46]: more output
[ 0:08:34.46]: ERRORLEVEL: 1
[ 0:08:34.46]: ERRORINFO: bar.cmd failed to continue
对于使用文件方法不是实时的时间的适当关注。
以下是与使用for
循环的问题类似的测试代码。
main2.cmd:
@echo off
setlocal
for /f "delims=" %%A in ('bar2.cmd') do call :log "%%~A"
:log
echo [%time%]: %~1
goto :eof
bar2.cmd:
@echo off
setlocal enabledelayedexpansion
echo start
for /l %%A in (2 2 10) do (
>nul timeout /nobreak /t 2
echo %%A secs [!time!]
)
输出:
[16:37:48.10]: start
[16:37:48.11]: 2 secs [16:37:40.14]
[16:37:48.11]: 4 secs [16:37:42.16]
[16:37:48.11]: 6 secs [16:37:44.17]
[16:37:48.11]: 8 secs [16:37:46.19]
[16:37:48.11]: 10 secs [16:37:48.10]
[16:37:48.11]:
每个回声应大约为2秒。
从输出可以看出,for
循环不返回stdout
实时。相反,似乎等待过程完成,
类似于管道的作用。
仅作为主脚本运行bar2.cmd
会实时回显
没有任何技巧可以影响main2.cmd
的输出。
答案 1 :(得分:0)
使用michael_heath的回答和Klitos Kyriacou的评论中的想法,这里是对问题第一部分的回答:
@echo off
for /f "delims=" %%a in ('bar^|powershell -noprofile -command "ForEach ($line in $Input) {Write-Output \"[$(Get-Date -Format hh:mm:ss.ff^)]: $line\"}"') do (call :log "%%a")
echo after loop error level: %ERRORLEVEL%
goto :eof
:log
echo during loop error level: %ERRORLEVEL%
echo %~1
goto :eof
我已将时间戳从:log
子例程移动到bar
输出到的流程。这只是回应时间戳前面的bar
输出。
这留下了问题的第二部分:你如何得到错误级别。这是一个非常复杂的问题,但幸运的是dbenham in another StackOverflow post已经解决了这个问题。