Plateforme Level Extreme
Abonnement
Profil corporatif
Produits & Services
Support
Légal
English
CreateProcess with redirected STDOUT
Message
De
25/01/2013 11:22:23
 
 
À
Tous
Information générale
Forum:
Visual C++
Catégorie:
Codage, syntaxe et commandes
Titre:
CreateProcess with redirected STDOUT
Divers
Thread ID:
01564066
Message ID:
01564066
Vues:
64
I have a function I've created which runs 7za.exe and captures its stdout. It works properly, but there is a delay between what would be seen were it writing to a console window, versus what I am able to see through the redirect using PeekNamedPipe() and ReadFile(). It appears to be due to buffering because when I finally am able to read something, it's a large chunk of data (about 100 lines of what would've been 'Compressing filename.ext" messages).

UPDATE: I found in MSDN where PeekNamedPipe() always returns 0 until the buffer size has been reached, even if the pipe is set to byte mode(why??). I switched it to use only ReadFile() reading 1 byte at a time, and it worked, but would block after the last byte was received waiting for the next byte to be received. I can spawn another thread which will write that last byte to the buffer so it can then test that the original app has terminated and politely exit the loop. Does anybody have a better solution?

Does anyone know of a way to make this work as in a console window?


General sequence I'm employing:
sa.nLength              = sizeof(SECURITY_ATTRIBUTES);
sa.bInheritHandle       = true;
sa.lpSecurityDescriptor = NULL;
if (!CreatePipe(&readHandle, &writeHandle, &sa, 0))
    // Report error

// These next four lines are things I've tried to get it to work better, none of them have changed anything:
SetNamedPipeHandleState(readHandle,  PIPE_READMODE_BYTE, NULL, NULL);
SetNamedPipeHandleState(writeHandle, PIPE_READMODE_BYTE, NULL, NULL);
int fileno = _open_osfhandle((long)writeHandle, 0);
_setmode(fileno, O_BINARY);

// Then I prepare and run the app
si.cb           = sizeof(STARTUPINFO);
si.dwFlags      = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
si.wShowWindow  = SW_HIDE;
si.hStdOutput   = writeHandle;
si.hStdError    = writeHandle;
if (!CreateProcessA(pathnameToExeOnly, fullCmdLine, NULL, NULL, true, 0, NULL, NULL, &si, &pi))
    // Report error

// Then I enter a loop
while (1)
{
    if (!PeekNamedPipe(readHandle, buffer, sizeof(buffer), &lnBytesRead, &lnTotalBytes, &lnBytesLeft))
        // Report error, break

    if (lnBytesRead)
    {
        if (!ReadFile(readHandle, buffer, sizeof(buffer) - 1, &lnBytesRead, NULL))
            // Report error, break

        // Here I process the read data block
    }
}

// Clean house
CloseHandle(pi.hThread); 
CloseHandle(pi.hProcess); 
CloseHandle(readHandle); 
CloseHandle(writeHandle); 
As I say, it works properly, but PeekNamedPipe() does not return any bytes until a large block is available. I'd like to have it transferring in binary byte mode.

TYIA!
Répondre
Fil
Voir

Click here to load this message in the networking platform