这是一个说明我问题的最小例子:
:: test.bat
@echo off
call test2.bat 2>&1 | findstr foo
echo done calling test2
:: test2.bat
@echo off
start /B notepad >NUL
echo done starting child process
在此示例中,在记事本关闭之前,findstr将无法完成,可能是因为记事本已从父cmd进程继承了stdout。如何修改test2.bat以便test.bat不会挂起?
答案 0 :(得分:2)
我相信我可以在没有任何批处理文件的情况下说明问题。直到notepad.exe关闭后,以下管道构造才会完成:
+-------+ +------+ +---+---+---+---+---+
|&buffer+------->+buffer+------->+ | | | | |
+-------+ +---+--+ +---+---+---+---+---+
我希望记事本会在一个完全与cmd.exe管道解除关联的新进程中执行,并且唯一被管道传输的东西就是START命令本身的输出(没有)。 START命令“立即”返回,但只要记事本正在运行,管道就会保持打开状态。
我不知道它是否是保持管道打开的继承I / O流,但我可以证明记事本进程以可能是问题根源的方式继承流。这与Issue with output redirection in batch提出的问题基本相同。
这是一个简单的批处理脚本: test.bat
start notepad | findstr "^"
请注意,由于@echo off
call :test >nul
echo done calling test.bat
exit /b
:test
start notepad
的重定向,当记事本启动时,stdout已被重定向到NUL。
现在看看当我从命令行发出一系列命令时会发生什么,从使用stdout重定向到文件的test.bat开始:
call :test >nul
我仍然被这种行为所震惊。这似乎完全不合逻辑。
我认为没有办法阻止cmd.exe的流继承。
也许Harry Johnston的建议可以解决问题(来自问题评论):“我写了一个非常简单的可执行文件来调用CreateProcess并禁用继承。”