intresting 'console' application

  • Thread starter Thread starter agostino
  • Start date Start date
A

agostino

I've realized an application that acts like a console.
It opens 2 pipes (CreatePipe api) and a process
(CreateProcess( .... ,"cmd.exe", ....).
So I get the output of cmd (the well-known console) and I'm able to send
commands to it.
I use ReadFile in a separate thread in order to get the output of the output
pipe.
I used a separate thread because if there's no more output, ReadFile blocks
and waits for new output.
It works fine in just a few lines of code. Now I would like to know when
ReadFile has finished to read the results. Actually when the ReadFile is
executing I've no way to detected whether it's locked (=it has finished) or
it's reading something.

thanks
Agostino
 
If you do this correctly, the pipe should hit an end of
file state when cmd.exe finishes. If you do it wrong,
you'll get the behavior you are describing. This is
probably because you've inherited both ends of the pipe
the child process is writing to, so you'll never see the
end of pipe because the other end of the pipe never
closes.

Create the pipe handles so they don't inherit. Then use
DuplicateHandle () to allow the child process' ends of
the pipes to be inherited and set those in your
STARTUPINFO data. Either use DUPLICATE_CLOSE_SOURCE or
close the original handles you duplicated. After
CreateProcess (), close those handles.

Here's a pseudo-code layout:

CreatePipe (&outRead, &outParentWrite, NULL, 0);
CreatePipe (&inParentRead, &inWrite, NULL, 0);
// the above aren't inheritable
DuplicateHandle (GetCurrentProcess (), outParentWrite,
GetCurrentProcess (), &outWrite, 0, TRUE,
DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
DuplicateHAndle (GetCurrentProcess (), inParentRead,
GetCurrentProces (), &inRead, 0, TRUE,
DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);

startupInfo.hStdInput = inRead;
startupInfo.hStdOutput = outWrite;
startupInfo.hStdError = outWrite;

CreateProcess (...)

// don't forget to close both the thread and process
handles when you are done with them. Usually, you don't
need the thread handle so close it now.
CloseHandle (procInfo.hThread);

// close the wrong ends of the pipes; they are now in the
child process and we don't need them here. Otherwise the
child will never get EOF, nor will we.
CloseHandle (outWrite);
CloseHandle (inRead);

// now, you may write to inWrite for the child's stdin,
and read from outRead from the child's stdout and stderr

// this is important so the child gets end of file on
it's stdin
CloseHandle (inWrite);

// if the child either closes it's output handles or
exits, you'll get EOF on inRead

If you use WaitFor..Object..() in the process handle, you
can bleed any last works from inRead. For this reason,
when I'm doing something similar to this, I
WaitForMultipleObjects..() on both the process handle and
my stdin reading babysitter thread, waiting for both to
be completed. I have the thread set up to exit when it
gets EOF or any other error reading outRead. Then I can
grab the process' exit code before closing the process
handle.
 
Back
Top