I've found some examples in the MSDN, but they only seem to work when the
app that's creating the console app, is a console app itself (IYSWIM:-) So
far I've tried:
- creating a pipe and setting the write handle in the STARTUPINFO struct
passed to CreateProcess() so that the created proc's STDOUT & STDERR point
to the pipe (no luck)
- creating a console process (a) which itself creates a console process
(b). the Win32 app creates a pipe, then passes its handles when it creates
(a). (a) then sets its STDOUT and ERR to this pipe, and creates (b) which
in theory now has this pipe as its STDIO.
I've tried many combinations of flags to CreateProcess(), and different
ways of using the pipe, and its driving me nuts!!!! Hope someone here can
help. Perhaps I'll have more luck looking at it with a fresh mind tomorrow.
*sigh*
So far I've looked at KB article Q150956, and an MSDN reference entitled
"Creating a child process with redirected input and output". These SEEM to
be what I need, and I can get the to work when all apps involved are
console apps, but NOT when the main app is a win32 app!! :-(
Cheers,
Pete.
PS this needs to work on WIN95 AND NT, so I can't use CreateNamedPipe.
--
----------------------------------------------------------------------------
-----------
Peter Keating - peterk@-snsys.NO_SPAM.com
The contents of this email are my own opinions, and not
those of SN systems Ltd.
(Remove ".NO_SPAM" from my email address to reply)
----------------------------------------------------------------------------
------------
1. Look at my homepage and get the "telnet server" for '95, for some code
examples of a Win32 GUI app that controls a console app via pipes...
Basically the process is:
1) AllocConsole in the GUI. This is a must.
2) Make two pipes with inheritable handles.
3) SetStdHandle() with the "remote" end of the pipes.
4) CreateProcess in the console to launch the app...
5) Read and write from your end of the pipes.
Chris.
--
======================================================================
<mailto:ch...@dbn.lia.net> Coding for Win95
Chris Becke <http://www.dbn.lia.net/users/chris>
======================================================================
: 1. Look at my homepage and get the "telnet server" for '95, for some code
: examples of a Win32 GUI app that controls a console app via pipes...
:
: Basically the process is:
:
: 1) AllocConsole in the GUI. This is a must.
:
: 2) Make two pipes with inheritable handles.
:
: 3) SetStdHandle() with the "remote" end of the pipes.
:
: 4) CreateProcess in the console to launch the app...
:
: 5) Read and write from your end of the pipes.
:
I have a really annoying problem dealing with pipes
under Windows95 which has to do with buffered stdout.
I will try to demonstrate this using the program shown below
(Console app, name it popen.c).
POPEN.EXE started with an argument will spawn itself in a mode which
outputs 10 lines to stdout one per second "unbuffered"
POPEN.EXE started without arguments will do the same but using "buffered"
output. This time, "ReadFile" is called once.
"ReadFile" is called ten times.
This works, because I have called setbuf(fp, NULL) in the spawned
process, which makes stdout unbuffered.
Now here's my real problem. I want to spawn applications I don't
have the sources for and still get unbuffered output.
With no luck!
Anyone can tell me what to do to make this work?
Thanks for any help,
Michael.
---snip------------------------
#define WIN32_LEAN_AND_MEAN
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#define PIPESIZE 1024
static HANDLE hReadPipe, hWritePipe;
static void error_exit (LPCSTR msg)
{
fprintf (stderr, "Error in %s\n", msg);
exit (1);
}
static DWORD watch_dog( HANDLE hPID )
{
DWORD dwResult = WaitForSingleObject (hPID, INFINITE);
CloseHandle (hReadPipe);
return dwResult;
}
static void child (BOOLEAN bBufferedOutput)
{
int i;
/* make stdout unbuffered, if an argument is given */
if (bBufferedOutput) {
fprintf (stdout, "child: stdout will be buffered\n");
}
else {
setbuf (stdout, NULL);
fprintf (stdout, "child: stdout will be unbuffered\n");
}
for (i = 0; i<10; i++) {
fprintf (stdout, "%d\n", i);
Sleep (1000);
}
fprintf (stderr, "Dad, I'm finished counting\n");
exit (0);
}
int main (int argc, char *argv[])
{
STARTUPINFO si;
PROCESS_INFORMATION pi;
HANDLE hThread;
DWORD dwRead, dwThreadID;
char szInput[ PIPESIZE + 1];
char szProg [256];
/*
** FUNCTION CODE:
*/
if (argc > 1) {
if (strcmp (argv[1], "buffered") == 0) {
child (TRUE);
}
else if (strcmp (argv[1], "unbuffered") == 0) {
child (FALSE);
}
else {
wsprintf (szProg, "%s %s", argv[0], "buffered");
fprintf (stderr, "Telling subprocess to buffer stdout\n");
fprintf (stderr, "for unbuffered output use: %s\n\n\n", argv[0]);
}
}
else {
wsprintf (szProg, "%s %s", argv[0], "unbuffered");
fprintf (stderr, "Telling subprocess NOT to buffer stdout\n");
fprintf (stderr, "for buffered output use: %s xxx\n\n\n", argv[0]);
}
/* if we are the parent, continue here */
if (!CreatePipe (&hReadPipe, &hWritePipe, NULL, PIPESIZE))
error_exit ("CreatePipe");
memset( &si, 0, sizeof(STARTUPINFO) ); // Initialize struct
si.cb = sizeof(STARTUPINFO);
si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
si.wShowWindow = SW_HIDE; // Don't show the console window (DOS box)
si.hStdOutput = hWritePipe; // Redirect command line
si.hStdError = hWritePipe;
si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
if (!CreateProcess (NULL, szProg,
NULL,NULL, TRUE, // bInheritHandler
NULL, NULL, NULL, &si, &pi))
error_exit ("CreateProcess");
CloseHandle (hWritePipe); // we don't need this handle
hThread = CreateThread( NULL, 0,
(LPTHREAD_START_ROUTINE)watch_dog,
(LPVOID)pi.hProcess, 0, &dwThreadID );
if( ! hThread )
fprintf (stderr, "Could not create watchdog thread\n");
while (ReadFile( hReadPipe, szInput, PIPESIZE, &dwRead, NULL ) != FALSE)
if( dwRead ) {
szInput [dwRead] = 0;
fprintf (stdout, "From %s: %s", szProg, szInput);
}
return 0;
}
---snap------------------------
Have you tried popen()? I've never used this function in Win 95 or NT,
but it works great on Unix and does what you want.
--
Bruce Beisel
bba...@pacbell.net
-Dan
On 10 Mar 1997 18:58:47 GMT, "Peter Keating"
<pet...@snsys.NO_SPAM.com> wrote:
>Hi all,
> I'm trying to do as the subject says - redirect the STDOUT and STDERR of a
>console process. What I need to do is this:
>1) a win32 app runs a console app (By calling CreateProcess() I'd imagine
>is the best way)
>2) All STDOUT and STDERR is send back to the win32 app via a pipe, for it
>to display in a message window
>
There are a couple things that make this a trickier problem to solve
than you would expect in a win32 app.
First, as you may already know, a win32 app doesn't have a stdin &
stdout. It doesn't even have valid handles for 0, 1 & 2.
The second thing is handles created by MS C-runtime calls (such as
_pipe() and dup2()) are NOT native OS handles; and native OS handles
are not automatically recognized by the C-runtime as valid handles!
To get the actual OS handle corresponding to a C-runtime handle call
_get_osfhandle(). To create a C-runtime handle from an OS handle call
_open_osfhandle(). These are part of the MS C-runtime library.
You might be better off spawning the console app with something like
_spawnlp() because it will make any C-runtime handles available to the
child process if it was written in MS C/C++.
Good Luck.
No, but a Win32 App does have STD_INPUT_HANDLE, STD_OUTPUT_HANDLE, and
STD_ERROR_HANDLE, all avaliable thru the Win32api call GetStdHandle().
stdin, stdout, and stderr, 0, 1, & 2 are provided by the c-runtime.
> The second thing is handles created by MS C-runtime calls (such as
> _pipe() and dup2()) are NOT native OS handles; and native OS handles
> are not automatically recognized by the C-runtime as valid handles!
yep. native file logic, and c-runtime file logic is so diffrent as to
necessitate that the CRT keeps a internal table of "real" handles that you
pretty much access by index (0,1,2, etc).
> To get the actual OS handle corresponding to a C-runtime handle call
> _get_osfhandle(). To create a C-runtime handle from an OS handle call
> _open_osfhandle(). These are part of the MS C-runtime library.
Aha. How to put real handles into the crt's handle array!.
> You might be better off spawning the console app with something like
> _spawnlp() because it will make any C-runtime handles available to the
> child process if it was written in MS C/C++.
hmmm, how? All it can really do is set the inheritability on the OS
handles.
This is incorrect. A console application (which is most definitely a
Win32 application) has standard stdin, stdout, and stderr handles. It's
only a GUI app which doesn't. If you don't need a GUI, it's often very
much simpler to write a console app - most of the programs I write are
console apps.
Chris
----------------------------------------------------------------
Chris Marriott, SkyMap Software, U.K. e-mail: ch...@skymap.com
Creators of fine astronomy software for Windows.
For full details, visit our web site at http://www.skymap.com
>Hi all,
> I'm trying to do as the subject says - redirect the STDOUT and STDERR of a
>console process. What I need to do is this:
>1) a win32 app runs a console app (By calling CreateProcess() I'd imagine
>is the best way)
>2) All STDOUT and STDERR is send back to the win32 app via a pipe, for it
>to display in a message window
>
>I've found some examples in the MSDN, but they only seem to work when the
>app that's creating the console app, is a console app itself (IYSWIM:-) So
>far I've tried:
I have the same problem. The sample program given in the win32
help file "Creating a child process with redirected input and output"
works with console apps only.
The only one sample I found that work with GUI app is
"DOS box pipe redirection" found at
http://www.frogpond.org/~markg/articles.html
but it as some limitations too.
blg
mailto:b...@mail.dotcom.fr
>Tim Watts <ti...@mindspring.com> wrote:
>> ...
>> You might be better off spawning the console app with something like
>> _spawnlp() because it will make any C-runtime handles available to the
>> child process if it was written in MS C/C++.
>hmmm, how? All it can really do is set the inheritability on the OS
>handles.
It makes them available through some environment variable trickery.
See "_spawn function overview" in VC++ 4.0 online help.
"The standard handles of a process may be redirected by a call to
SetStdHandle, in which case GetStdHandle returns the redirected handle. If
the standard handles have been redirected, you can specify the CONIN$ value
in a call to the CreateFile function to get a handle of a console's input
buffer. Similarly, you can specify the CONOUT$ value to get a handle of a
console's active screen buffer. "
Mario Contestabile
cont...@cam.org
> > I'm trying to do as the subject says - redirect the STDOUT and STDERR
of a
> > console process. What I need to do is this:
> > 1) a win32 app runs a console app (By calling CreateProcess() I'd
imagine
> > is the best way)
> > 2) All STDOUT and STDERR is send back to the win32 app via a pipe, for
it
> > to display in a message window
>
I've just done a somewhat similar thing (a console app that grabs stdout
& sends it to a window, sorta like MORE). I did it like this:
* The GUI app creates a mailslot (I believe these work on 95 as well as
NT)
* The console app opens the mailslot with CreateFile() (making sure to
specify FILE_SHARE_READ)
* The console app reads the redirected output & sends it through the
mailslot.
Your situation is not as simple, but this might work with the GUI ->
console app -> console app aproach.
hope this helps...
tom