【问题标题】:Unable To Run Command-Line Instructions From WinForm无法从 WinForm 运行命令行指令
【发布时间】:2014-08-23 11:41:23
【问题描述】:

在学习 C# 的过程中,我创建了一个基于 winforms 的应用程序,通过单击 button 来 ping google.com。所以,当我点击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();

    }
}
}


【问题讨论】:

  • 你的意思是收到2或3个回复后退出?
  • 我正在得到任何东西。命令提示符启动,保持空白 20 秒然后关闭。
  • 在域之后添加 `-t'。 IE。 @"/C ping www.google.com -t" 然后再试一次
  • 你应该对 output 变量做一些有用的事情。
  • @Shell : 而且,现在命令提示符永远保留在那里 :(

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


【解决方案1】:

您正在使用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();
}

第二个选项可确保您的 UI 在您单击按钮并等待 ping 命令完成后不会冻结。

【讨论】:

【解决方案2】:

这一行将使您无法在控制台中看到任何内容:

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);

【讨论】:

  • 噢,不公平,你的答案和我一样;-)
猜你喜欢
  • 2013-12-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-10
  • 1970-01-01
  • 1970-01-01
  • 2018-07-18
相关资源
最近更新 更多