I used this code as a starting point, in an MFC dialog, to display output from a called process. It was rather painless as this is well documented. He tells you why he is doing what. It should be suitable as you are working with the Windows platform. But as Alf points out, cross platform is something else.
*UPDATE
The link to Microsofts answer. And this with the code
Even Better!
And sehe should get the credit. In a nut shell...
This is the child process.
#include <iostream>
#include <chrono>
#include <thread>
int main() {
using namespace std::chrono_literals;
std::string str;
int i{};
for (;;) {
std::this_thread::sleep_for(600ms);
if (i++ > 4)
break;
str = "test: " + std::to_string(i);
std::cout << str << std::endl;
}
return 0;
}
Be sure to use std::endl
in the child so the stream gets flushed. Then...
#include <boost/process.hpp>
#include <boost/asio.hpp>
#include <boost/process/async.hpp>
#include <iostream>
#include <iomanip>
int main() {
namespace bp = boost::process;
boost::asio::io_context context;
bp::async_pipe out(context);
//correct this path to point to your 'process.exe'
bp::child c(R"(D:\cpp\stack_test\Debug\process.exe)", bp::std_out > out, context);
std::vector<std::string> lines;
boost::asio::streambuf buffer;
std::function<void()> read_loop;
read_loop = [&] {
boost::asio::async_read_until(out, buffer, "\n", [&](boost::system::error_code code, std::size_t size) {
if (!code) { //good to go
std::cerr << "received: " << size << " bytes" << std::endl;
auto b = buffers_begin(buffer.data()), m = b + size;
std::string in(b, m);
std::cout << in;
lines.emplace_back(b, m);
buffer.consume(size);
read_loop();
}
else {
std::cerr << "Oops: " << code.message() << std::endl;
}
});
};
read_loop();
context.run();
for (auto& line : lines) {
std::cout << line;
}
return c.exit_code();
}
If you don't want context.run()
to block, put it in a thread and work it like this in the main loop.