在学习C#的过程中,我创建了一个基于winforms的应用程序,通过点击google.com
来ping button
。因此,当我单击button
时,command prompt
出现但ping
命令未运行,并且最终command prompt
窗口在一段时间后仍然存在。
怎么了 ?为什么ping
没有执行?
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button_Click(object sender, EventArgs e)
{
Process p = new Process();
p.StartInfo.FileName = "cmd.exe";
p.StartInfo.Arguments = @"/C ping www.google.com";
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.UseShellExecute = false;
p.Start();
string output = p.StandardOutput.ReadToEnd();
p.WaitForExit();
}
}
}
答案 0 :(得分:3)
您正在使用RedirectStandardOutput = true
,这意味着应用程序的输出不会输出到控制台,而是您必须阅读它,就像您最后使用string output =
一样。实际上,如果您调试应用程序,您将在输出变量中看到应用程序的输出。
如果将其设置为false,则输出将显示在弹出的控制台窗口中。请记住,如果您这样做,则无法从StandardOutput
读取。
所以这取决于你想做什么。任
RedirectStandardOutput = false
并让命令的输出显示在自己的窗口中在附加说明中,如果项目中有一个名为" hostBox"的文本框。例如,您可以从文本框中获取文本并ping该主机,只需将参数设置为新主机即可。
因此按钮的更新回调将如下所示:
private void button_Click(object sender, EventArgs e) {
Process p = new Process();
p.StartInfo.FileName = "ping.exe";
// you can put together any arguments you'd like in the string format call
// for the moment only the text from hostBox is needed
// for instance string.Format("{0} -t", hostBox.Text); if you want to ping indefinately
p.StartInfo.Arguments = string.Format("{0}", hostBox.Text);
p.StartInfo.CreateNoWindow = true;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.UseShellExecute = false;
p.Start();
string output;
// read output one line at the time. If the output is null, the application quit
while ((output = p.StandardOutput.ReadLine()) != null) {
textBox1.Text += output + Environment.NewLine;
Application.DoEvents();
}
p.WaitForExit();
}
另请注意,我使用的是ReadLine
而不是ReadToEnd
,这意味着在获取输出之前,您不必等待应用程序结束。我还在表单中添加了一个textBox1,以便从应用程序中附加文本。 Application.DoEvents
调用确保UI线程处理每个读取行之间的事件。另一种选择是在一个新线程中启动该进程,并通过对表单的Invoke
调用将输出编组回来。
使用线程可以看起来像这样:
private void button_Click(object sender, EventArgs e) {
new Thread(() => {
Process p = new Process();
p.StartInfo.FileName = "ping.exe";
// you can put together any arguments you'd like in the string format call
// for the moment only the text from hostBox is needed
// for instance string.Format("{0} -t", hostBox.Text); if you want to ping indefinately
p.StartInfo.Arguments = string.Format("{0}", hostBox.Text);
p.StartInfo.CreateNoWindow = true;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.UseShellExecute = false;
p.Start();
string line;
// read output one line at the time. If the output is null, the application quit
while ((line = p.StandardOutput.ReadLine()) != null) {
string output1 = line;
textBox1.Invoke(new Action(() => {
textBox1.Text += output1 + Environment.NewLine;
}));
}
p.WaitForExit();
}).Start();
}
第二个选项可确保在您点击按钮并等待ping命令完成后,您的用户界面不会冻结。
答案 1 :(得分:3)
此行将阻止您在控制台中看到任何内容:
p.StartInfo.RedirectStandardOutput = true;
告诉Process
您打算拦截返回数据,您似乎想要这样做:
String output = p.StandardOutput.ReadToEnd();
但是,你什么都不做。我改为这个并取得了不错的结果:
Process p = new Process();
p.StartInfo.FileName = "cmd.exe";
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.UseShellExecute = false;
p.StartInfo.CreateNoWindow = true; //don't show the console at all
p.Start();
String output = p.StandardOutput.ReadToEnd();
String msg = "No result";
if (!String.IsNullOrEmpty(output))
msg = output;
MessageBox.Show(msg);