我正在研究C ++ / CLI winforms 如何将标准输出重定向到文本框? 我关注了这个视频,但它没有用 https://www.youtube.com/watch?v=BDTCviA-5M8
我可以在控制台窗口看到输出,但直到进程完成GUI冻结!
ProcessStartInfo ^psi = gcnew ProcessStartInfo("D://ffmpeg.exe", "-y -i D://1.avi D://process.mp4");
psi->WindowStyle = ProcessWindowStyle::Hidden;
psi->UseShellExecute = false;
psi->RedirectStandardOutput = true;
process->StartInfo = psi;
process->Start();
String^ details = process->StandardOutput->ReadToEnd();
textBox1->Text = details;
Console::WriteLine(details);
我哪里错了?
答案 0 :(得分:1)
您读取标准输出有什么问题。由于您的代码只涉及一个threadf,因此没有其他选择可以让所有事情连续发生。如果要查看长时间运行的命令工具的进度/输出,则需要使用Process实例中的OutputDataReceived事件。
以下代码使用该技术来实现您的目标:
ref class ProcessForm:Form
{
TextBox ^textBox1 = gcnew TextBox();
Button ^button = gcnew Button();
public:
ProcessForm() {
this->Width = 325;
this->Height = 450;
textBox1->Top = 20;
textBox1->Width = 300;
textBox1->Height = 400;
textBox1->Multiline = true;
button->Text = "Start";
button->Click += gcnew System::EventHandler(this, &ProcessForm::OnClick);
this->Controls->Add(textBox1);
this->Controls->Add(button);
}
void ProcessForm::OnClick(System::Object ^sender, System::EventArgs ^e)
{
Process ^process = gcnew Process();
// "D://ffmpeg.exe", "-y -i D://1.avi D://process.mp4"
ProcessStartInfo ^psi = gcnew ProcessStartInfo("cmd.exe", "/c dir \\*.exe /s");
psi->WindowStyle = ProcessWindowStyle::Hidden;
psi->UseShellExecute = false;
psi->RedirectStandardOutput = true;
process->StartInfo = psi;
// handle incoming data from the standard output stream
process->OutputDataReceived += gcnew DataReceivedEventHandler(this, &ProcessForm::OnOutputDataReceived);
process->Start();
// start reading from the standard ouput stream on a different thread
process->BeginOutputReadLine();
// prevent starting again ...
process->Exited += gcnew System::EventHandler(this, &ProcessForm::OnExited);
this->button->Enabled = false;
}
delegate void UpdateHandler(System::String ^text);
// output the stuff on screen
void ProcessForm::Update(System::String ^text)
{
textBox1->Text += text;
Console::WriteLine(text);
}
// is invoked on a seperate thread if the process writes
// to the console
void ProcessForm::OnOutputDataReceived(System::Object ^sender, System::Diagnostics::DataReceivedEventArgs ^e)
{
// handle switching to the UI thread
if (textBox1->InvokeRequired)
{
UpdateHandler^ handler = gcnew UpdateHandler(this, &ProcessForm::Update);
textBox1->Invoke(handler, e->Data);
}
else
{
Update(e->Data);
}
}
// if we're done enable the button again
void ProcessForm::OnExited(System::Object ^sender, System::EventArgs ^e)
{
this->button->Enabled = true;
}
};
请注意,需要使用Invoke
,因为从非UI线程调用事件方法。