首页 文章

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

提问于
浏览
-1

我可以在 STARTUPINFO 结构中使用 STARTF_USESTDHANDLES 标志重定向 stdinstdoutstderr 进程,由 CreateProcess 创建 .

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

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

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

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

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

如果在写入所有字节之前管道缓冲区已满,则WriteFile不会返回,直到另一个进程或线程使用ReadFile来提供更多缓冲区空间 .

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

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

1 回答

  • 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 设备是否由Microsoft在任何地方正式记录 . 但是如果你对此熟悉的话,那就是's been part of Windows since before there was Windows. MS-DOS 1.0 supported it. It works like Unix' s /dev/null .

相关问题