5

根据 MSDN,这会将子标准输出重定向到父标准输出,但它没有,有什么问题?

   PROCESS_INFORMATION pi;
   STARTUPINFOA si;

   ZeroMemory( &si, sizeof(si) );
   si.cb = sizeof(si);
   ZeroMemory( &pi, sizeof(pi) );
   si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
   si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
   si.dwFlags |= STARTF_USESTDHANDLES;

   BOOL ret = CreateProcessA( 0, cmd_line, 0, 0, TRUE, CREATE_NO_WINDOW, 0, 0, & si, & pi);

使用 DuplicateHandle 没有帮助:

HANDLE out, err;//global variables
...
PROCESS_INFORMATION pi;
STARTUPINFOA si;

ZeroMemory( &si, sizeof(si) );
si.cb = sizeof(si);
ZeroMemory( &pi, sizeof(pi) );  
BOOL ret = DuplicateHandle( GetCurrentProcess(), GetStdHandle(STD_OUTPUT_HANDLE),  GetCurrentProcess(), &out, 0, TRUE, DUPLICATE_SAME_ACCESS);//todo check ret
ret = DuplicateHandle( GetCurrentProcess(), GetStdHandle(STD_ERROR_HANDLE),  GetCurrentProcess(), &err, 0, TRUE, DUPLICATE_SAME_ACCESS);//todo check ret

si.hStdOutput = out;
si.hStdError = err;
si.dwFlags |= STARTF_USESTDHANDLES;

ret = CreateProcessA( 0, cmd_line, 0, 0, TRUE, CREATE_NO_WINDOW, 0, 0, & si, & pi);
4

3 回答 3

6

BOOL ret = CreateProcessA( 0, cmd_line, 0, 0, TRUE, CREATE_NO_WINDOW, 0, 0, & si, & pi);

CREATE_NO_WINDOW导致此行为,将其删除:

BOOL ret = CreateProcessA( 0, cmd_line, 0, 0, TRUE, 0, 0, 0, & si, & pi);

于 2013-11-07T19:18:25.027 回答
2

首先,我赞同迈克尔的建议。你根本不应该再使用 A 版本,除非出于某种疯狂的原因你需要支持 Windows 98。提示:你不需要。您应该只使用 W 版本。总是#define UNICODE!!!

根据文档:

STARTF_USESTDHANDLES 0x00000100hStdInput和包含附加信息hStdOutputhStdError members

如果在调用进程创建函数之一时指定了此标志,则句柄必须是可继承的,并且函数的 bInheritHandles参数必须设置为 TRUE。有关详细信息,请参阅处理继承。

返回的句柄GetStdHandle不一定是可继承的句柄,它们可能是不可继承的,也可能是伪句柄。事实上,它们可能根本不存在,它们可能是 null 或 INVALID_HANDLE_VALUE——你也需要检查一下。

要从不可继承句柄或伪句柄中获取可继承句柄,您需要使用DuplicateHandle

于 2013-09-27T13:36:30.160 回答
1

不要将父进程的 stdout/stderr 句柄直接传递给子进程。用于CreatePipe()创建读/写管道,将它们的写入端点分配给子进程 stdout/stderr 句柄,然后让父进程用于ReadFile()从管道读取并将任何接收到的数据写入其自己的 stdout/stderr 需要。MSDN 展示了如何使用CreatePipe()它:

创建具有重定向输入和输出的子进程

于 2013-09-27T15:27:58.103 回答