Reading output from console program
I need to read output from native C++ console application in my C++/.NET. There are many articles about this, but most wait until the process ends to read the output, which I don't want to, I need to read it immediately after it is "cout-ed" by the process (and don't want to block the GUI while doing so, but that's something I can do on my own). I tried two ways. One:
Diagnostics::Process ^process = gcnew Diagnostics::Process;
process->StartInfo->FileName = pathToExecutable;
process->StartInfo->RedirectStandardOutput = true;
process->StartInfo->UseShellExecute = false;
process->StartInfo->CreateNoWindow = true;
process->StartInfo->Arguments = "some params";
process->EnableRaisingEvents = true;
process->OutputDataReceived += gcnew Diagnostics::DataReceivedEventHandler( GUI::Form1::consoleHandler );
process->Start();
process->BeginOutputReadLine();
And the handler:
System::Void GUI::Form1::consoleHandler( System::Object^ sendingProcess, System::Diagnostics::DataReceivedEventArgs^ outLine ){
GUI::Form1::contentForConsole += outLine->Data + "\n";
}
But debugger c开发者_如何学运维onfirmed it is called only after the process is finished.
On my second attempt I tried to create custom watching thread:
Diagnostics::Process ^process = gcnew Diagnostics::Process;
process->StartInfo->FileName = pathToExecutable;
process->StartInfo->RedirectStandardOutput = true;
process->StartInfo->RedirectStandardError = true;
process->StartInfo->UseShellExecute = false;
process->StartInfo->CreateNoWindow = true;
process->StartInfo->Arguments = "some params";
processStatic = process; // static class member
process->Start();
System::Windows::Forms::MethodInvoker^ invoker = gcnew System::Windows::Forms::MethodInvoker(reader);
invoker->BeginInvoke(nullptr, nullptr);
And the thread function, it waits on the ReadLine function until the process finishes:
System::Void GUI::Form1::reader(){
System::String^ str;
while ((str = geogenProcess->StandardOutput->ReadLine()) != nullptr)
{
contentForConsole += str; // timer invoked handler then displays this, but this line is called only once the process is finished
}
}
The process executable ouputs many lines of text over time span ranging from several seconds to several minutes (depending on the actual task).
I managed to find the answer myself in the end. Both ways of reading console output are perfectly functional. The problem was in the console application. I didn't know it is necessary to flush the console output manually to make it available to other apps.
So after replacing:
cout << "Some stuff " << some_var << " more stuff\n";
with
cout << "Some stuff " << some_var << " more stuff\n" << flush;
works like charm.
Why don't redirect called process' output to a file and read that file from your program? If the child process flushes its output well, then you got a quite good response.
精彩评论