仅重定向子进程stdin并从stdout和stderr中删除数据

时间:2014-09-01 13:11:38

标签: c++ stdout pipe

我可以在STARTF_USESTDHANDLES结构中使用STARTUPINFO标记来重定向由stdin创建的stdoutstderrCreateProcess进程。< / p>

Documentation 对于这种情况说(STARTF_USESTDHANDLES标志存在):

  

hStdInput,hStdOutput和hStdError成员包含其他成员   信息。如果在调用其中一个进程时指定了此标志   创建函数,句柄必须是可继承的和函数的   bInheritHandles参数必须设置为TRUE。欲获得更多信息,   请参阅处理继承。

但对于那些成员本身(hStdInput等),同一个文档说(例如 - hStdError):

  

如果dwFlags指定STARTF_USESTDHANDLES,则此成员是标准   进程的错误句柄。否则,该成员将被忽略   标准错误的默认值是控制台窗口的缓冲区。

如果我将管道连接到子进程stdout并且从中读取数据,则其缓冲区将溢出,并且根据this doc,子进程将在尝试一段时间后挂起在stdout上写数据,因为

  

如果在写入所有字节之前管道缓冲区已满,则写入WriteFile   直到另一个进程或线程使用ReadFile才能返回   更多的缓冲空间。

hStdOutput标志出现时,我可以安全地为hStdError结构的STARTUPINFOSTARTF_USESTDHANDLES成员传递 NULL 以避免这种情况吗?或者我必须使轮询线程从管道擦除数据以防止其缓冲区溢出?

我想要可靠的解决方案,所以,请你能发布任何文档说明这是从stdout中删除数据的合法方法。

1 个答案:

答案 0 :(得分:1)

打开NUL设备并将其用作hStdOutputhStrError句柄。写入NUL设备的任何数据都将被忽略而不会导致错误。这比没有句柄更可取,因为标准输出的写入失败或子进程中的标准错误可能导致它过早退出。请确保将句柄继承为文档中提到的。

类似的东西:

SECURITY_ATTRIBUTES secattr;
secattr.nLength = sizeof secattr;
secattr.lpSecurityDescriptor = NULL;
secattr.bInheritHandle = TRUE;
hnul = CreateFile("NUL", GENERIC_WRITE, 0, &secattr, OPEN_EXISTING, 0, NULL);
startupinfo.hStdOutput = hnul;
startupinfo.hStdError = hnul;

我不确定微软是否在任何地方正式记录NUL设备。然而,在Windows出现以前,它一直是Windows的一部分。 MS-DOS 1.0支持它。如果您熟悉它,它就像Unix的/dev/null一样。