[英]ProcessInfo and RedirectStandardOutput
我有一個在命令窗口中調用另一個進程的應用程序,並且該進程更新了輸出到控制台窗口的統計信息。 我認為這是一個相當簡單的操作,但我似乎無法讓它工作。 我錯過了什么嗎?
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();
理想情況下,我想要的是當我點擊的那個過程中的輸出發生變化或者數據進入閱讀器時我從它那里得到事件。
任何幫助都會很棒,我覺得這是一個新手問題,但似乎遺漏了一些東西。
我以前經歷過這個。 有時,您調用輸出到控制台的過程與這種輸出重定向不兼容。 在這種情況下,我很幸運能夠修改外部流程來解決這個問題。
您可以嘗試在另一個輸出到控制台的進程上運行您的代碼,看看它是否正常工作。 它現在對我來說是正確的。
編輯:
我去拉了一個我用來做這個的代碼塊。 這是在將進程輸出重定向到窗口的 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);
});
}
}
我不確定您遇到了什么問題,但如果您希望在輸出生成后立即對其采取行動,請嘗試連接到進程的OutputDataReceived
事件。 您可以指定處理程序以異步方式接收來自進程的輸出。 我已經成功地使用了這種方法。
Process p = new Process();
ProcessStartInfo info = p.info;
info.UseShellExecute = false;
info.RedirectStandardOutput = true;
info.RedirectStandardError = true;
p.OutputDataReceived += p_OutputDataReceived;
p.ErrorDataReceived += p_ErrorDataReceived;
p.Start();
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);
}
有關詳細信息,請參閱 Process 的OutputDataReceived事件。
使用 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();
有趣的是,您不能同時讀取標准輸出和標准錯誤:
如果您同時重定向標准輸出和標准錯誤,然后嘗試讀取兩者,例如使用以下 C# 代碼。
[C#]
字符串輸出 = p.StandardOutput.ReadToEnd();
字符串錯誤 = p.StandardError.ReadToEnd();
p.WaitForExit();
在這種情況下,如果子進程向標准錯誤寫入任何文本,它將阻塞該進程,因為父進程在完成從標准輸出讀取之前無法從標准錯誤中讀取。 但是,在進程結束之前,父進程不會從標准輸出中讀取。 針對這種情況的推薦解決方案是創建兩個線程,以便您的應用程序可以在單獨的線程上讀取每個流的輸出。
流動的代碼在 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();
}
}
檢查你期望的輸出沒有被發送到 StandardError 輸出而不是 StandardOutput 輸出
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.