Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

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);
like image 273
Michal Avatar asked Sep 27 '13 13:09

Michal


2 Answers

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

CREATE_NO_WINDOW causes this behavior, remove it:

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

like image 111
user2957539 Avatar answered Sep 24 '22 22:09

user2957539


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

like image 41
Ben Avatar answered Sep 25 '22 22:09

Ben