Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

CreateProcess and redirected output -- is it possible to...

2,060 views
Skip to first unread message

stephen clover

unread,
May 30, 2002, 10:59:39 PM5/30/02
to
i want to do something which might seem a bit unusual, and I don't think
it's going to be possible. i'm interested if anyone has suggestions about
a strategy for achieving this:
- parent process starts a child process
- child process stdout is redirected to a file
- child process stderr is displayed in console window

the first two are easy to achieve:
- open file
- copy file handle to hStdOutput in STARTUPINFO struct 'si'
- add STARTF_USESTDHANDLES to si.dwFlags
- call CreateProcess with bInheritHandles TRUE and CREATE_NEW_CONSOLE in
dwCreationFlags

but the third not so -- obviously redirecting standard i/o handles is an
all-or-nothing thing and since i can't get the stderr handle of the console
which is created when i call CreateProcess i can't set the hStdError field
of the STARTUPINFO struct.

neither can i create a new console window and redirect the stderr output to
that because the parent process is a console-mode application.

any suggestions welcomed...
stephen/.

Jugoslav Dujic

unread,
May 31, 2002, 5:53:32 AM5/31/02
to
"stephen clover" <scl...@xtra.co.nz> wrote in message
news:ce31e45b.02053...@posting.google.com...

|
| neither can i create a new console window and redirect the stderr output to
| that because the parent process is a console-mode application.

Why not? AFAIK CREATE_NEW_CONSOLE flag to CreateProcess is supposed
to work in your situation.

Jugoslav
___________
www.geocities.com/jdujic

stephen clover

unread,
Jun 3, 2002, 6:28:40 PM6/3/02
to
"Jugoslav Dujic" <jdujic...@uns.ns.ac.yu> wrote:
> "stephen clover" <scl...@xtra.co.nz> wrote

> | neither can i create a new console window and redirect the stderr
> | output to that because the parent process is a console-mode application.
>
> Why not? AFAIK CREATE_NEW_CONSOLE flag to CreateProcess is supposed
> to work in your situation.

sorry i should have been more clear -- i meant that i can't use the
Free/AllocConsole API or else i'll lose my app's existing console.

if i specify CREATE_NEW_CONSOLE i get a new console all right -- but it's
blank -- because to redirect the StdOut to a file i've had to use the
STARTF_USESTDHANDLES in the STARTUPINFO dwFlags field and i can't
assign anything to the StdError handle because the console window hasn't
been created yet and ... phew! ...
or am i missing something?
-stephen/.

Norman Bullen

unread,
Jun 3, 2002, 8:45:20 PM6/3/02
to

Are you trying to get stderr of the sub-process to come back to the
console window of the original process?

If so, use GetStdHandle(STD_ERROR_HANDLE) and (probably)
DuplicateHandle() get an inheritable handle to stderr in the original
process. Put that in hStdError in STARTUPINFO when you call
CreateProcess().

Norm

stephen clover

unread,
Jun 4, 2002, 7:05:22 PM6/4/02
to
Norman Bullen <no...@BlackCatAssociates.com> wrote:
> Are you trying to get stderr of the sub-process to come back to the
> console window of the original process?
>
> If so, use GetStdHandle(STD_ERROR_HANDLE) and (probably)
> DuplicateHandle() get an inheritable handle to stderr in the original
> process. Put that in hStdError in STARTUPINFO when you call
> CreateProcess().

thanks for the tip but no, i want the stderr output to appear in
the console window of the child process.

imagine you're running a Win32 console-mode app, one which outputs to stdout
and stderr, at a command prompt, and you redirect stdout to a file:

cmd> myapp.exe > output.txt

the stderr still appears in the command-prompt window.

that's the behaviour i want -- spawn the app using CreateProcess with
CREATE_NEW_CONSOLE, redirect the StdOut output to a file but have the
StdErr output still appear in the child process console window.

char *lpCommandLine = "myapp.exe";
char *lpFileName = "output.txt";
BOOL bInheritHandles;
DWORD dwCreationFlags;
HANDLE htdOutRedirectionFile;
STARTUPINFO si;
PROCESS_INFORMATION pi;

// Redirected output file
hStdOutRedirectionFile = CreateFile(lpFileName, ...);

// Startup-Information
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
si.dwFlags |= STARTF_USESTDHANDLES;
si.hStdOutput = hStdOutRedirectionFile;
// but what can i possibly set si.hStdError to here?
// si.hStdOutput = ???;

// 'Spawn' process
bInheritHandles = TRUE;
dwCreationFlags = CREATE_NEW_CONSOLE;
CreateProcess(NULL, // Application name
lpCommandLine, // Command line string
NULL, // Process security attributes
NULL, // Thread security attributes
bInheritHandles, // Handle inheritance flag
dwCreationFlags, // Creation flags
NULL, // New environment block
NULL, // Current directory name
&si, // STARTUPINFO
&pi); // PROCESS_INFORMATION
etc...

hope this is readable ;)
stephen/.

Norman Bullen

unread,
Jun 4, 2002, 11:48:23 PM6/4/02
to
stephen clover wrote:
>
> Norman Bullen <no...@BlackCatAssociates.com> wrote:
> > Are you trying to get stderr of the sub-process to come back to the
> > console window of the original process?
> >
> > If so, use GetStdHandle(STD_ERROR_HANDLE) and (probably)
> > DuplicateHandle() get an inheritable handle to stderr in the original
> > process. Put that in hStdError in STARTUPINFO when you call
> > CreateProcess().
>
> thanks for the tip but no, i want the stderr output to appear in
> the console window of the child process.
>
> imagine you're running a Win32 console-mode app, one which outputs to stdout
> and stderr, at a command prompt, and you redirect stdout to a file:
>
> cmd> myapp.exe > output.txt
>
> the stderr still appears in the command-prompt window.
>
> that's the behaviour i want -- spawn the app using CreateProcess with
> CREATE_NEW_CONSOLE, redirect the StdOut output to a file but have the
> StdErr output still appear in the child process console window.
>
\
How about this:

Write a small program that expects argv[1] to be the name of a file
(i.e. output.txt) and the remainder of the command line to be the name
of another executable (i.e. myapp.exe) and any arguments that it
requires.

This small program opens output.txt with an inheritable handle and then
uses CreateProcess() to run myapp.exe with stdout of myapp.exe
redirected to the handle of output.txt and stderr of myapp.exe
redirected to the console belonging to this small program.

Now, in your original application, you can use CreateProcess() with
CREATE_NEW_CONSOLE to run this small program with an appropriate command
line.

I haven't tried it but it looks like it ought to work.

Norm

Jugoslav Dujic

unread,
Jun 5, 2002, 8:52:40 AM6/5/02
to
"Norman Bullen" <no...@BlackCatAssociates.com> wrote in message
news:3CFD8A07...@BlackCatAssociates.com...

| stephen clover wrote:
| >
| > Norman Bullen <no...@BlackCatAssociates.com> wrote:
| > > Are you trying to get stderr of the sub-process to come back to the
| > > console window of the original process?
| > >
| > > If so, use GetStdHandle(STD_ERROR_HANDLE) and (probably)
| > > DuplicateHandle() get an inheritable handle to stderr in the original
| > > process. Put that in hStdError in STARTUPINFO when you call
| > > CreateProcess().
| >
| > thanks for the tip but no, i want the stderr output to appear in
| > the console window of the child process.
| >
| > imagine you're running a Win32 console-mode app, one which outputs to stdout
| > and stderr, at a command prompt, and you redirect stdout to a file:
| >
| > cmd> myapp.exe > output.txt
| >
| > the stderr still appears in the command-prompt window.

Doh... what a chicken & egg situation indeed...

| > that's the behaviour i want -- spawn the app using CreateProcess with
| > CREATE_NEW_CONSOLE, redirect the StdOut output to a file but have the
| > StdErr output still appear in the child process console window.
| >
| \
| How about this:

<snip>
Another idea would be to modify the source of the 2nd application
so that it's essentially a WinMain app with console:

int WINAPI WinMain(hInstance,...

hOutHandle = GetStdHandle(STD_OUTPUT_HANDLE); // remember this...
AllocConsole(); // this will reset handles to new ones;
SetStdHandle(STD_OUTPUT_HANDLE, hOutHandle) // set this one back

alternatively, you could use console app instead, but which
would do a FreeConsole before the code above.

Jugoslav
___________
www.geocities.com/jdujic

Jugoslav Dujic

unread,
Jun 5, 2002, 8:55:23 AM6/5/02
to

| alternatively, you could use console app instead, but which
| would do a FreeConsole before the code above.

...oh, I've just remembered that there's also DETACHED_PROCESS
flag for CreateProcess, which (by my reading at least) does not
create new console for the process at all.

Jugoslav
___________
www.geocities.com/jdujic


stephen clover

unread,
Jun 6, 2002, 6:53:28 PM6/6/02
to
hey guys...
both these solutions are interesting but i really already considered
them -- i'm looking for a general solution which works for any
console-mode application, not just ones which i can modify the source for
and i want it in a stand-alone application, without having to spawn
any 'worker' processes or exes.

this is as much about solving this problem (i have a particular instance
for which this is a problem) as finding out whether or not this is a bug/
shortcoming in the Win32 API.

the solution i have just settled on -- which seems a little too obvious
to be the answer to my prayers, but it's a start -- albeit a kinda ugly
one -- is this:

assume that, like DOS, the _unredirected_ standard I/O handles to an
application (a console-mode one, anyway) are always the same -- a quick
test shows that StdOut appears to default to 7, and StdError to 11.
so the quik-fix (tm) is

si.hStdError = (HANDLE)11;

this works just fine.

whether or not i can rely on this value to remain constant is anyone's
guess.

thanks for your ideas,
stephen/.

0 new messages