How to pass an input and retrieve an output to a child process in C language

richardtk_1 picture richardtk_1 · Jan 30, 2014 · Viewed 7.2k times · Source

I have an exe program in Windows which in the terminal works as follows

> program.exe parameter01 file
entry01 (user types entry01)
output01
entry02 (user types entry02)
output02
...
until the combination Ctrl+D is pressed.

I need to create a "child process" in a C language which is capable to run the program and sent entries to the "child process" and receive the output in a char[] or string.

I know I have to use the CreateProcess method but I don't know how to pass an entry like an input and retrieve the output, How can I do this?

I have seen this using Java but I need to implement this functionality in C language.

Answer

JuanR picture JuanR · Jan 30, 2014

Use the STARTUPINFO structure

You must set the attribute hStdInput.

More and less, this is what you need (it is C++ code and it may not compile, but you'll get the idea):

std::string GetProcessOutput(HANDLE hStdOutProcess) {
    std::stringstream strStream;
    char lpBuffer[2] = {0};
    DWORD nBytesRead;
    while(true){
        BOOL bResult = ReadFile(hStdOutProcess, lpBuffer, sizeof(char), &nBytesRead, NULL);
        if (bResult && nBytesRead) {
            strStream << lpBuffer;
        } else {
            break;
        }
    }
    return strStream.str();
}

void RunAndGetOutout() {
    HANDLE hProcessStdOutRead = NULL;
    HANDLE hProcessStdOutWrite = NULL;

    SECURITY_ATTRIBUTES saAttr;
    saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); 
    saAttr.bInheritHandle = TRUE;  // allow to inherit handles from parent process
    saAttr.lpSecurityDescriptor = NULL; 

    if(!CreatePipe(&hProcessStdOutRead, &hProcessStdOutWrite, &saAttr, 0)) {
        return nResult;
    }
    if(!SetHandleInformation(hProcessStdOutRead, HANDLE_FLAG_INHERIT, 0)) {
        return nResult;
    }

    STARTUPINFO startInfo;
    PROCESS_INFORMATION processInfo;
    char cmdLine[ MAX_PATH*2 +40] = {0};
    char currentDir[MAX_PATH] = {0};

    ZeroMemory(&startInfo, sizeof(startInfo));
    startInfo.cb = sizeof(startInfo);
    startInfo.hStdOutput = hProcessStdOutWrite; // set the handle
    startInfo.dwFlags |= STARTF_USESTDHANDLES; // attention with this one

    ZeroMemory(&processInfo, sizeof(processInfo));

    GetCurrentDirectory(MAX_PATH, currentDir);
    sprintf(cmdLine, "\"%s\" %s", (const char*)m_path2Process, (const char*)m_processArgs);

    if(CreateProcess( NULL, cmdLine, NULL, NULL, TRUE, 0, NULL, currentDir, &startInfo, &processInfo)) {

        cout << GetProcessOutput(hProcessStdOutRead) << endl;

        CloseHandle(processInfo.hThread);
        CloseHandle(processInfo.hProcess);
    }

    CloseHandle(hProcessStdOutRead);
    CloseHandle(hProcessStdOutWrite)
}