从进程重定向 StandardOutput
Redirect StandardOutput from a process
我正在使用 C++/CLI winforms
如何将标准输出重定向到文本框?
我关注了这个视频,但是没有用
https://www.youtube.com/watch?v=BDTCviA-5M8
我可以在控制台中看到输出 window,但是直到进程完成 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);
我哪里错了?
您对标准输出的读取有问题。由于您的代码中只涉及一个线程,因此没有其他选择可以让所有事情连续发生。如果您想查看长 运行 命令工具的 progress/output,您需要使用 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 线程调用的。
我正在使用 C++/CLI winforms 如何将标准输出重定向到文本框? 我关注了这个视频,但是没有用 https://www.youtube.com/watch?v=BDTCviA-5M8
我可以在控制台中看到输出 window,但是直到进程完成 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);
我哪里错了?
您对标准输出的读取有问题。由于您的代码中只涉及一个线程,因此没有其他选择可以让所有事情连续发生。如果您想查看长 运行 命令工具的 progress/output,您需要使用 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 线程调用的。