How to Execute bat file using CreateProcess and Simultaneously Print/Read Its Output in C++?

80 Views Asked by At

So I've tried to execute a bat file that install a software for windows. The code works, however it only outputs the once the process is done. Is there a way to synchronize execution and redirecting/reading console output?

I tried to follow this but still get the same output: Is it possible to embed a command prompt in a win32 app?

I've tried to use thread but it still didn't work. The batch was executed and after that the output is then read and printed. Which is not a goal of my project.

Please refer to the code below:

#include <windows.h>
#include <iostream>
#include <string>
#include <thread>

// Function to capture and print the output of a child process
void CaptureChildProcessOutput(HANDLE hChildStdOut) {
    char buffer[4096];
    DWORD bytesRead;

    while (true) {
        if (!ReadFile(hChildStdOut, buffer, sizeof(buffer), &bytesRead, nullptr) || bytesRead == 0)
            break;

        std::string output(buffer, bytesRead);
        std::cout << output;
    }
}

int main() {
    SECURITY_ATTRIBUTES saAttr;
    saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
    saAttr.bInheritHandle = TRUE;
    saAttr.lpSecurityDescriptor = NULL;

    HANDLE hChildStdOutRead, hChildStdOutWrite;
    if (!CreatePipe(&hChildStdOutRead, &hChildStdOutWrite, &saAttr, 0)) {
        std::cerr << "Failed to create pipe." << std::endl;
        return 1;
    }

    STARTUPINFOA si; // Use STARTUPINFOA instead of STARTUPINFO (ANSI version)
    PROCESS_INFORMATION pi;
    ZeroMemory(&si, sizeof(STARTUPINFOA));
    si.cb = sizeof(STARTUPINFOA);
    si.hStdError = hChildStdOutWrite;
    si.hStdOutput = hChildStdOutWrite;
    si.dwFlags |= STARTF_USESTDHANDLES;

    // Convert wide string to narrow string
    std::wstring cmdLineW = L"cmd.exe /C InstallSoftware.bat"; // Change this to your batch file
    std::string cmdLineA(cmdLineW.begin(), cmdLineW.end());

    if (!CreateProcessA(NULL, &cmdLineA[0], NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi)) {
        std::cerr << "CreateProcess failed." << std::endl;
        return 1;
    }

    CloseHandle(hChildStdOutWrite);

    // Create a thread to capture and print the child process output
    std::thread outputThread(CaptureChildProcessOutput, hChildStdOutRead);

    // Wait for the child process to complete
    WaitForSingleObject(pi.hProcess, INFINITE);

    // Close the thread and process handles
    outputThread.join();
    CloseHandle(hChildStdOutRead);
    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);

    return 0;
}

0

There are 0 best solutions below