我有一个应用程序,它在命令窗口中调用另一个进程,该进程已更新输出到控制台窗口的统计信息。我认为这是一个相当简单的操作,但我似乎无法让它工作。我错过了什么吗?
string assemblyLocation = Assembly.GetExecutingAssembly().Location;
Process process = new Process
{
ProcessStart =
{
RedirectStandardOutput = true,
UseShellExecute = false,
WindowStyle = ProcessWindowStyle.Hidden,
Arguments = arg,
FileName = assemblyLocation.Substring(0, assemblyLocation.LastIndexOf("\\")) + "\\ffmpeg.exe",
CreateNoWindow = true
}
};
process.Start();
Console.WriteLine(process.StandardOutput.ReadToEnd());
process.WaitForExit();
理想情况下,我想要的是输出在我触及的过程中发生变化,或者数据进入读者,我会从中获取事件。
任何帮助都会很棒,我觉得这是一个新手问题,但似乎缺少一些东西。
答案 0 :(得分:48)
我以前经历过这个。有时,您调用输出到控制台的进程的方式与此类输出重定向不兼容。在这种情况下,我很幸运能够修改外部进程来解决这个问题。
您可以尝试在另一个输出到控制台的进程上运行代码,看看它是否正常工作。它现在读到我的权利。
编辑:
我去了一个我曾经做过的代码块。这是在WPF应用程序中,它将进程输出重定向到窗口。注意事件绑定。由于这是WPF,我必须调用我的调用来写出数据。由于您不担心阻止,因此您应该只需将其替换为:
Console.WriteLine(e.Data);
希望它有所帮助!
private static void LaunchProcess()
{
Process build = new Process();
build.StartInfo.WorkingDirectory = @"dir";
build.StartInfo.Arguments = "";
build.StartInfo.FileName = "my.exe";
build.StartInfo.UseShellExecute = false;
build.StartInfo.RedirectStandardOutput = true;
build.StartInfo.RedirectStandardError = true;
build.StartInfo.CreateNoWindow = true;
build.ErrorDataReceived += build_ErrorDataReceived;
build.OutputDataReceived += build_ErrorDataReceived;
build.EnableRaisingEvents = true;
build.Start();
build.BeginOutputReadLine();
build.BeginErrorReadLine();
build.WaitForExit();
}
// write out info to the display window
static void build_ErrorDataReceived(object sender, DataReceivedEventArgs e)
{
string strMessage = e.Data;
if (richTextBox != null && !String.Empty(strMessage))
{
App.Instance.Dispatcher.BeginInvoke(DispatcherPriority.Send, (ThreadStart)delegate()
{
Paragraph para = new Paragraph(new Run(strMessage));
para.Margin = new Thickness(0);
para.Background = brushErrorBrush;
box.Document.Blocks.Add(para);
});
}
}
答案 1 :(得分:21)
我不确定您遇到了什么问题,但是如果您希望在生成后立即对输出采取行动,请尝试挂钩进程的OutputDataReceived
事件。您可以指定处理程序以从进程异步接收输出。我成功地使用了这种方法。
ProcessStartInfo info = new ProcessStartInfo(...)
info.UseShellExecute = false;
info.RedirectStandardOutput = true;
info.RedirectStandardError = true;
Process p = Process.Start(info);
p.OutputDataReceived += p_OutputDataReceived;
p.ErrorDataReceived += p_ErrorDataReceived;
p.BeginOutputReadLine();
p.BeginErrorReadLine();
p.WaitForExit();
...
void p_OutputDataReceived(object sender, DataReceivedEventArgs e)
{
Console.WriteLine("Received from standard out: " + e.Data);
}
void p_ErrorDataReceived(object sender, DataReceivedEventArgs e)
{
Console.WriteLine("Received from standard error: " + e.Data);
}
有关详细信息,请参阅流程中的OutputDataReceived事件。
答案 2 :(得分:11)
使用lambda表达式等:
var info = new ProcessStartInfo(path)
{
RedirectStandardError = true,
RedirectStandardOutput = true,
UseShellExecute = false,
Verb = "runas",
};
var process = new Process
{
EnableRaisingEvents = true,
StartInfo = info
};
Action<object, DataReceivedEventArgs> actionWrite = (sender, e) =>
{
Console.WriteLine(e.Data);
};
process.ErrorDataReceived += (sender, e) => actionWrite(sender, e);
process.OutputDataReceived += (sender, e) => actionWrite(sender, e);
process.Start();
process.BeginOutputReadLine();
process.BeginErrorReadLine();
process.WaitForExit();
答案 3 :(得分:4)
有趣的是,您无法同时读取标准输出和标准错误:
如果您重定向标准输出和标准错误,然后尝试同时读取两者,for 示例使用以下C#代码。
[C#]
string output = p.StandardOutput.ReadToEnd();
string error = p.StandardError.ReadToEnd();
p.WaitForExit();
在这种情况下,如果子进程将任何文本写入标准错误,它将阻止 进程,因为父进程在完成之前无法读取标准错误 从标准输出读取。但是,父进程不会从标准读取 输出直到过程结束。这种情况的推荐解决方案是创建两个 线程,以便您的应用程序可以在单独的线程上读取每个流的输出。
答案 4 :(得分:1)
流动代码在VS2010中工作
void OnOutputDataReceived(object sender, DataReceivedEventArgs e)
{
if (String.IsNullOrEmpty(e.Data) == false)
{
new Thread(() =>
{
this.Dispatcher.Invoke(new Action(() =>
{
// Add you code here
}));
}).Start();
}
}
答案 5 :(得分:0)
检查您期望的输出是否未发送到StandardError输出而不是StandardOutput输出