找回密码
 注册
搜索
[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
查看: 74002|回复: 26

[其他] [已解决]批处理使用管道后,如何捕获errorlevel?

[复制链接]
发表于 2015-3-21 10:18:14 | 显示全部楼层 |阅读模式
本帖最后由 shootman2 于 2015-3-27 01:02 编辑

假如使用了管道符后,再去捕获errorlevel时发现,其值已变为0,即便之前的命令是否返回0。
如下代码

call myCommand.bat|mtee /d /t /+ sysLog.log

如果调用myCommand.bat后返回errorlevel值为1,但是执行如上代码后,errorlevel值又变为0了,
求大神帮助!!!

评分

参与人数 1PB +2 收起 理由
Batcher + 2 感谢给帖子标题标注[已解决]字样

查看全部评分

发表于 2015-3-21 18:26:53 | 显示全部楼层
(call myCommand.bat&Set ExitCode=!ErrorLevel!)|mtee /d /t /+ sysLog.log
这样呢?
 楼主| 发表于 2015-3-21 23:34:21 | 显示全部楼层
回复 2# bailong360

我试过了,不行的!
发表于 2015-3-21 23:50:33 | 显示全部楼层
  1. call myCommand.bat&>$tmp.txt Echo;!ErrorLevel!|mtee /d /t /+ sysLog.log
  2. Set /P ExitCode=<$tmp.txt
复制代码
那就这样吧
 楼主| 发表于 2015-3-24 15:17:25 | 显示全部楼层
回复 4# bailong360


    还是没有达到我想要的结果,errorlevel是获取正确了,但是没有正确的将打印结果输出到sysLog.log文件中
发表于 2015-3-24 22:15:11 | 显示全部楼层
管道中不允许有独立的内部命令或代码块,所以这个 call myCommand.bat|mtee /d /t /+ sysLog.log 相当于
  1. cmd /c call myCommand.bat|mtee /d /t /+ sysLog.log
复制代码
而只要是外部命令,一定会改变退出码,所以你取到的永远是 mtee 的退出码

至于怎么解决...这里举一个比较复杂的例子:
  1. for /f "delims=" %%a in ('cmd /c "(call myCommand.bat 1>&2 2>nul & call echo %%errorlevel^^%%) 1>&2 2>&1|mtee /d /t /+ sysLog.log" 2^>^&1') do (
  2.         echo call myCommand.bat 的退出码是 %%a
  3. )
复制代码
1>&2 2>&1 的意思是交换句柄 1 和 2,很久以前发现的小技巧,一直用不上,也不知道有没有人用过
发表于 2015-3-24 22:59:37 | 显示全部楼层
回复 6# CrLf


    请教一下在这里交换句柄指向的意义......表示这么高深的代码全然看不懂
 楼主| 发表于 2015-3-24 23:08:17 | 显示全部楼层
管道中不允许有独立的内部命令或代码块,所以这个 call myCommand.bat|mtee /d /t /+ sysLog.log 相当于而只 ...
CrLf 发表于 2015-3-24 22:15



    CrLf 大神,太牛了!32个赞给你。但是能不能稍微简化一下,不好理解呀!
发表于 2015-3-24 23:48:35 | 显示全部楼层
本帖最后由 CrLf 于 2015-3-25 01:00 编辑

回复 7# bailong360


回复 8# shootman2


仔细想一下其实不需要交换句柄 1 和 2,化简一下:(外交部发言人 for /f 代表党和人民热烈欢迎英勇突围的 %errorlevel%,并致以最诚挚的问候)
  1. for /f "delims=" %%a in ('"(call myCommand.bat 2>nul & call echo %%errorlevel^^%% 1>&2)|mtee /d /t /+ sysLog.log 2>&1"') do (
  2.         echo call myCommand.bat 的退出码是 %%a
  3. )
复制代码
----------------------------------------------------------------------------------------------------
经过预处理变成这样:(for /f 欢迎突围的 %errorlevel%)
  1. for /f "delims=" %a in ('"(call myCommand.bat 2>nul & call echo %errorlevel^^% 1>&2)|mtee /d /t /+ sysLog.log 2>&1"') do (
  2.         echo call myCommand.bat 的退出码是 %a
  3. )
复制代码
----------------------------------------------------------------------------------------------------
for /f 隐含了一个 cmd,执行起来相当于:(这里没发生什么,只是在句柄 1 中包含了 %errorlevel% 的内容)
  1. cmd /c "(call myCommand.bat 2>nul & call echo %errorlevel^^% 1>&2)|mtee /d /t /+ sysLog.log 2>&1"
复制代码
----------------------------------------------------------------------------------------------------
管道前的代码块触发了一个内层的 cmd,外面的 cmd 执行的代码相当于这样:(因为 mtee 已经取走了所有来自句柄 1 的输出,所以句柄 1 为空,可以放心将句柄 2 再重定向到句柄 1)
  1. (cmd /c "(call myCommand.bat 2>nul & call echo %errorlevel^^% 1>&2)"|mtee /d /t /+ sysLog.log) 2>&1
复制代码
----------------------------------------------------------------------------------------------------
里面那个隐含的 cmd 执行的是这样:(把这句柄 1 的输出都交给 mtee 进行处理,句柄 2 的未被读取)
  1. cmd /c (call myCommand.bat 2>nul & call echo %errorlevel^% 1>&2)
复制代码
----------------------------------------------------------------------------------------------------
管道前的部分执行的是这样:(先将 call myCommand.bat 的句柄 1 输出到句柄 2 中,并屏蔽原有的句柄 2 输出,再输出其 %errorlevel% 到正常的句柄 2)
  1. (
  2.         call myCommand.bat 2>nul
  3.         call echo %errorlevel% 1>&2
  4. )
  5. rem 因为 cmd 里不存在的变量不会被扩展,所以只要不存在 errorlevel^ 变量,%errorlevel^% 就不会被扩展
复制代码
----------------------------------------------------------------------------------------------------
接下来,请按 ctrl+A 全选变成蓝底白字,然后从下往上看粗体字

评分

参与人数 2技术 +2 收起 理由
DAIC + 1 虽不懂,但觉厉!
bailong360 + 1 原来如此,又收获了不少知识

查看全部评分

 楼主| 发表于 2015-3-25 12:08:05 | 显示全部楼层
回复  bailong360


回复  shootman2


仔细想一下其实不需要交换句柄 1 和 2,化简一下:(外交部 ...
CrLf 发表于 2015-3-24 23:48



    myCommand.bat是有输出的,当我执行您写的代码后,结果是这样的。。。
1
call myCommand.bat 的退出码是 2015-03-25 12:06:11.833 1231312312
call myCommand.bat 的退出码是 2015-03-25 12:06:11.837 12312312312312312
请按任意键继续. . .

    myCommand.bat内容如下
@echo off
echo 1231312312
echo 12312312312312312
exit /b 1
发表于 2015-3-25 16:16:44 | 显示全部楼层
本帖最后由 CrLf 于 2015-3-25 20:26 编辑

回复 10# shootman2


    ok,那你试试这个:
  1. @echo off

  2. rem 1>nul 3>&1 4>&1

  3. (
  4.         (
  5.                 (
  6.                         call myCommand.bat 2>nul & call echo %%errorlevel^^^^%% 1>&2
  7.                 )|(
  8.                         mtee /d /t /+ sysLog.log
  9.                 )
  10.         ) 1>&2 2>&3 | (
  11.                 set /p err=&call exit /b %%err^^%%
  12.         )
  13. ) 1>&3

  14. echo myCommand.bat 的退出码为 %errorlevel%

  15. pause
复制代码
用了句柄重定向中的句柄备份、句柄交换两个小技巧
伪代码是这样:
  1. 【备份干净的句柄 1 到句柄 3 中备用】

  2. (
  3.         (
  4.                 (
  5.                         【屏蔽 myCommand.bat 句柄 2】
  6.                         【输出 %errorlevel% 到句柄 2】
  7.                 ) | (
  8.                         【mtee 接收句柄 1 并将其内容原样输出到句柄 1】
  9.                 )
  10.         ) 【交换句柄 1 和 2,因为此时句柄 1 是“脏”的,所以从句柄 3 获取原始的句柄 1】 | (
  11.                 【获取句柄 1 的值保存到变量】
  12.                 【以此变量为退出码设定最终的 %errorlevel%】
  13.         )
  14. ) 【将句柄 1 还原为原始的句柄 1】

  15. 【显示 myCommand.bat 的退出码 %errorlevel%】
复制代码
 楼主| 发表于 2015-3-26 00:04:53 | 显示全部楼层
回复 11# CrLf


    哈哈!实现了,感谢您,对您的景仰有如滔滔江水!

  不过还有个问题,当myCommand.bat有报错的话,是直接打印出来的,您的代码,就直接给屏蔽掉了。
  能帮忙再改改嘛?
发表于 2015-3-26 00:16:06 | 显示全部楼层
回复 12# shootman2


如果一定要不生成临时文件的话那没办法,StdOut 和 StdErr 一定要有一个用来输出 %errorlevel%
但如果可以用临时文件就很简单了,你把它输出到文本,比如这样:
  1. @echo off
  2. (call myCommand.bat & call echo %%errorlevel^^%% >errorlevel.txt) |mtee /d /t /+ sysLog.log
  3. set /p error=<errorlevel.txt
  4. echo myCommand.bat 的退出码为 %error%
  5. pause
复制代码
 楼主| 发表于 2015-3-26 10:07:41 | 显示全部楼层
回复 13# CrLf


    嗯!正解。。。大神,你太牛了!对您的景仰有如滔滔江水,永远都流不尽啊!
发表于 2015-3-26 11:25:04 | 显示全部楼层
回复 14# shootman2
问题得到解决后请在标题最前面注明[已解决]
http://www.bathome.net/thread-3473-1-1.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|手机版|小黑屋|批处理之家 ( 渝ICP备10000708号 )

GMT+8, 2026-3-19 10:12 , Processed in 0.022483 second(s), 8 queries , File On.

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表