将子进程输出重定向到缓冲区

时间:2015-08-10 20:57:26

标签: c++ winapi mfc

我正在使用Visual Studio C ++。我有子进程输出需要重定向到某个缓冲区。任何人都可以帮助我解决这个问题。

char ReadBuff[4096 + 1];
DWORD ReadNum;
for (;;) 
{
    BOOL success = ReadFile(pipes[ParentRead], ReadBuff, sizeof(ReadBuff) - 1, &ReadNum, NULL);
    std::cout << success;
    if (!success || !ReadNum)
        break;
    ReadBuff[ReadNum] = 0;
    std::cout << ReadBuff;
}

我为ParentRead,ParentWrite,ChildWrite,ChildRead创建了句柄。我关闭了除ParentRead之外的所有句柄。所以,我可以从中读取内容。当我调试它时,它会中断并且成功为0.任何人都可以让我知道它无法读取文件。非常感谢你

1 个答案:

答案 0 :(得分:1)

这不是我自己的代码,我很久以前就找到了它。这里的链接(http://snipplr.com/view/35935/)可能不是原始来源,所以我也在发布代码。

所以这段代码将运行一个命令,并将所有输出转换为CString,WaitForSingleObject( pi.hProcess, INFINITE );将使您的主进程挂起,直到子进程完成。

// Execute a command and get the results in a CString.
// Synchronously launches a child process and waits up to 2 seconds for completion.
// Uses a pipe to get the output of the child process.
// Does not pipe to stdin of child process.
// Example usage:
// CString str;
// str = ExecCmd( "ping 127.0.0.1 -n 99 " ); // This ping command will be terminated early before the -n 99 completes.
// str.Replace( "\x0d\x0d\x0a", "\x0d\x0a" ); // fixes some ugly non-standard line terminators created by ping.
//
// str = ExecCmd( "java -version" ); // A more practical usage.
//
CString ExecCmd( CString pCmdArg,CString csParameters, CString csDir)
{
    // Handle Inheritance - to pipe child's stdout via pipes to parent, handles must be inherited.
    // SECURITY_ATTRIBUTES.bInheritHandle must be TRUE
    // CreateProcess parameter bInheritHandles must be TRUE;
    // STARTUPINFO.dwFlags must have STARTF_USESTDHANDLES set.

    CString strResult = L""; // Contains result of cmdArg.

    HANDLE hChildStdoutRd; // Read-side, used in calls to ReadFile() to get child's stdout output.
    HANDLE hChildStdoutWr; // Write-side, given to child process using si struct.

    BOOL fSuccess;

    // Create security attributes to create pipe.
    SECURITY_ATTRIBUTES saAttr = {sizeof(SECURITY_ATTRIBUTES)} ;
    saAttr.bInheritHandle = TRUE; // Set the bInheritHandle flag so pipe handles are inherited by child process. Required.
    saAttr.lpSecurityDescriptor = NULL;

    // Create a pipe to get results from child's stdout.
    // I'll create only 1 because I don't need to pipe to the child's stdin.
    if ( !CreatePipe(&hChildStdoutRd, &hChildStdoutWr, &saAttr, 0) )
    {
        return L"cannot create pipe";
    }

    STARTUPINFO si;
    ZeroMemory(&si, sizeof(si));
    si.cb = sizeof(si);
    PROCESS_INFORMATION pi;
    ZeroMemory(&pi, sizeof(pi));

    si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES; // STARTF_USESTDHANDLES is Required.
    si.hStdOutput = hChildStdoutWr; // Requires STARTF_USESTDHANDLES in dwFlags.
    si.hStdError = hChildStdoutWr; // Requires STARTF_USESTDHANDLES in dwFlags.
    // si.hStdInput remains null.
    si.wShowWindow = SW_HIDE; // Prevents cmd window from flashing. Requires STARTF_USESHOWWINDOW in dwFlags.

    CString csCommand(pCmdArg);
    csCommand+= L" ";
    csCommand+= csParameters;
    // Create the child process.
    fSuccess = CreateProcess(NULL, csCommand.GetBuffer(0), NULL, NULL, TRUE, 0, NULL,
        csDir, &si, &pi);
//     fSuccess = CreateProcess(
//         NULL,
//         (LPSTR)pCmdArg, // command line
//         NULL, // process security attributes
//         NULL, // primary thread security attributes
//         TRUE, // TRUE=handles are inherited. Required.
//         CREATE_NEW_CONSOLE, // creation flags
//         NULL, // use parent's environment
//         NULL, // use parent's current directory
//         &si, // __in, STARTUPINFO pointer
//         &pi); // __out, receives PROCESS_INFORMATION

    if (! fSuccess)
    {
        return L"cannot create process";
    }

    // Wait until child processes exit. 
    WaitForSingleObject( pi.hProcess, INFINITE );
    TerminateProcess( pi.hProcess, 0 ); // Kill process if it is still running. Tested using cmd "ping blah -n 99"

    // Close the write end of the pipe before reading from the read end of the pipe.
    if (!CloseHandle(hChildStdoutWr))
    {
        return L"cannot close handle";
    }

    // Read output from the child process.
    for (;;)
    {
        DWORD dwRead;
        CHAR chBuf[4096];

        // Read from pipe that is the standard output for child process.
        bool done = !ReadFile( hChildStdoutRd, chBuf, 4096, &dwRead, NULL) || dwRead == 0;
        if( done )
        {
            break;
        }

        // Append result to string.
        strResult += CString( chBuf, dwRead) ;
    }

    // Close process and thread handles.
    CloseHandle( hChildStdoutRd );

    // CreateProcess docs specify that these must be closed.
    CloseHandle( pi.hProcess );
    CloseHandle( pi.hThread );

    return strResult;
}