无法从WinForm运行命令行指令

时间:2014-08-23 11:41:23

标签: c# winforms shell command-line command-prompt

在学习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();

    }
}
}


CMD

2 个答案:

答案 0 :(得分:3)

您正在使用RedirectStandardOutput = true,这意味着应用程序的输出不会输出到控制台,而是您必须阅读它,就像您最后使用string output =一样。实际上,如果您调试应用程序,您将在输出变量中看到应用程序的输出。

如果将其设置为false,则输出将显示在弹出的控制台窗口中。请记住,如果您这样做,则无法从StandardOutput读取。

所以这取决于你想做什么。任

  • 直接启动ping命令并读取其输出,或
  • 设置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);