我如何使用" start"命令没有继承子进程中的句柄?

时间:2016-03-18 18:26:54

标签: windows batch-file cmd

这是一个说明我问题的最小例子:

:: 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不会挂起?

1 个答案:

答案 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并禁用继承。”