Здравствуйте Alexche, вы писали:

RM>>Создается анонимный канал(pipe), затем инициализируется в STARTUPINFO hStdOutput хэндлом записи созданного канала и

RM>>dwFlags |= STARTF_USESTDHANDLES, а затем делается CreateProcess c bInheritHandles=TRUE, ну и ReadFile из хэндла чтения канала.

A>Работает, но очень медленно: программа уже завершила работу, а выведенные сообщения еще долго читаются, а после того, как все прочитается программа зависает на ReadFile

A>(ни один MessageBox не срабатывает)
A>Что здесь неправильно?

A>do

A>{
A> fSuccess = ReadFile( hReadPipe, &bReadBuffer, 1, &cbReadBuffer, NULL);
A> if( !fSuccess )
A> if( GetLastError() == ERROR_BROKEN_PIPE )
A> {
A> MessageBox("Child has died");
A> break; // child has died
A> }
A> else MessageBox("Pipe error");

A> {

A> ...
A> }
A>} while( fSuccess && cbReadBuffer );

Медленно наверное потому, что читается по одному байту. Я бы сделал буфер
побольше.

А виснет скорее всего потому, что ты не закрываешь хэндл того конца пайпа,
который отдаешь дочернему процессу. В результате для этого конца пайпа
получается два хэндла: один в дочернем процессе и один в твоем процессе.
Когда дочерний завершается, его хэндл закрывается, но поскольку есть еще
один незакрытый хэндл, пайп остается живым с обоих сторон и для ReadFile
нет никакой причины возвращать управление.

Другими словами, надо делать так:

SECURITY_ATTRIBUTES sa;
sa.nLength = sizeof(sa);
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = TRUE;

HANDLE hRead, hWrite;
if (!CreatePipe(&hRead, &hWrite, &sa, 0))
    ...

STARTUPINFO si;
memset(&si, 0, sizeof(si));

si.cb = sizeof(si);
si.dwFlags = STARTF_USESTDHANDLES;
si.hStdInput = ...;
si.hStdOutput = hWrite;
si.hStdError = ...;

if (!CreateProcess(NULL, pszCmdLine, NULL, NULL,
    TRUE, NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi))
    ...

CloseHandle(hWrite);  // <--

while (ReadFile(hRead, ...))
{
     ...
}
Автор: Alex Fedotov    Оценить