简体   繁体   中英

CreateProcess: redirect child stdout to parent stdout in C++/Windows

According to MSDN this redirects child stdout to parent stdout, but it does not, what is wrong?

   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);

using DuplicateHandle does not help:

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);

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);

Firstly I second Michael's advice. You shouldn't be using the A versions at all, ever again, unless for some crazy reason you need to support Windows 98. Hint: You don't. You should only ever be using the W versions. Always #define UNICODE !!!

According to the documentation:

STARTF_USESTDHANDLES 0x00000100 The hStdInput , hStdOutput , and hStdError members contain additional information.

If this flag is specified when calling one of the process creation functions, the handles must be inheritable and the function's bInheritHandles parameter must be set to TRUE. For more information, see Handle Inheritance.

The handles returned by GetStdHandle are not necessarily inheritable handles, they may be non-inheritable or may be pseudo-handles. In fact they may not exist at all, they may be null or INVALID_HANDLE_VALUE -- you need to check for that too.

To get an inheritable handle from a non-inheritable handle or pseudohandle, you need to use DuplicateHandle

Don't pass the parent's stdout/stderr handles directly to the child process. Use CreatePipe() to create read/write pipe(s), assign their writing endpoints to the child process stdout/stderr handles, then have the parent process use ReadFile() to read from the pipes and write any received data to its own stdout/stderr as needed. MSDN shows how to use CreatePipe() for that:

Creating a Child Process with Redirected Input and Output

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM