C# 如何在多行文本框上打印ping.exe的进度?

C# 如何在多行文本框上打印ping.exe的进度?,c#,C#,我有一个文本框和一个按钮。该按钮调用Ping(),我希望Ping的任何进度都显示在textBox1中 void Ping() { p = new Process(); p.StartInfo.FileName = "ping"; p.StartInfo.UseShellExecute = false; p.StartInfo.RedirectStandardOutput

我有一个文本框和一个按钮。该按钮调用
Ping()
,我希望Ping的任何进度都显示在
textBox1

        void Ping()
        {
            p = new Process();
            p.StartInfo.FileName = "ping";
            p.StartInfo.UseShellExecute = false;
            p.StartInfo.RedirectStandardOutput = true;
            p.StartInfo.Arguments = "www.microsoft.com";
            p.Start();
            textBox1.Text = p.StandardOutput.ReadToEnd();
            p.WaitForExit();
        }
如何实现?我上面写的当前实现没有显示进度,而是显示最终输出

async void Test()
{
    await Ping("www.google.com");
}


Task Ping(string host)
{
    var tcs = new TaskCompletionSource<object>();

    ProcessStartInfo psi = new ProcessStartInfo();
    psi.FileName = "ping.exe";
    psi.UseShellExecute = false;
    psi.RedirectStandardOutput = true;
    psi.Arguments = host;

    var proc = Process.Start(psi);

    proc.OutputDataReceived += (s, e) => {
            Action action = () => textBox1.Text += e.Data + Environment.NewLine;
            this.Invoke(action);
        };

    proc.Exited += (s, e) => tcs.SetResult(null);

    proc.EnableRaisingEvents = true;
    proc.BeginOutputReadLine();

    return tcs.Task;
}

话虽如此,我还是会使用
Ping
类,而不是启动外部应用程序

var ping = new System.Net.NetworkInformation.Ping();
var pingReply = await ping.SendPingAsync("www.google.com");
Console.WriteLine("{0} {1} {2}",pingReply.Address, 
                                pingReply.RoundtripTime, 
                                pingReply.Status);

话虽如此,我还是会使用
Ping
类,而不是启动外部应用程序

var ping = new System.Net.NetworkInformation.Ping();
var pingReply = await ping.SendPingAsync("www.google.com");
Console.WriteLine("{0} {1} {2}",pingReply.Address, 
                                pingReply.RoundtripTime, 
                                pingReply.Status);

更新

收到评论后,我继续用WinForms重新完成了整个项目

这是更新的代码和屏幕截图,希望对您有所帮助

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;
using System.Threading;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {  
        private Process p;

        public Form1()
        {
            InitializeComponent();

        }

        private void cmdPing_Click(object sender, EventArgs e)
        {
            p = new Process();
            startNewThread();
        }

        public void Log(string line)
        {
            txtOutput.Text += line + System.Environment.NewLine;
        }

        private void startNewThread()
        {
            Thread x = new Thread(new ThreadStart(Ping));
            x.IsBackground = true;
            x.Start();
        }

        private void Ping()
        {
            p.StartInfo.FileName = "ping.exe";
            p.StartInfo.CreateNoWindow = true;
            p.StartInfo.UseShellExecute = false;
            p.StartInfo.RedirectStandardOutput = true;
            p.StartInfo.Arguments = txtAddress.Text;
            p.Start();

            while (p.StandardOutput.Peek() > -1)
            {
                this.Invoke((MethodInvoker)delegate() { Log(p.StandardOutput.ReadLine()); });
                p.StandardOutput.DiscardBufferedData();
            }

        }

    }
}
表单截图


更新

收到评论后,我继续用WinForms重新完成了整个项目

这是更新的代码和屏幕截图,希望对您有所帮助

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;
using System.Threading;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {  
        private Process p;

        public Form1()
        {
            InitializeComponent();

        }

        private void cmdPing_Click(object sender, EventArgs e)
        {
            p = new Process();
            startNewThread();
        }

        public void Log(string line)
        {
            txtOutput.Text += line + System.Environment.NewLine;
        }

        private void startNewThread()
        {
            Thread x = new Thread(new ThreadStart(Ping));
            x.IsBackground = true;
            x.Start();
        }

        private void Ping()
        {
            p.StartInfo.FileName = "ping.exe";
            p.StartInfo.CreateNoWindow = true;
            p.StartInfo.UseShellExecute = false;
            p.StartInfo.RedirectStandardOutput = true;
            p.StartInfo.Arguments = txtAddress.Text;
            p.Start();

            while (p.StandardOutput.Peek() > -1)
            {
                this.Invoke((MethodInvoker)delegate() { Log(p.StandardOutput.ReadLine()); });
                p.StandardOutput.DiscardBufferedData();
            }

        }

    }
}
表单截图


@Nicolamasatti:我不知道怎么做。你可以使用
ReadToEnd()
直到最后才会返回。。。相反,请尝试ReadLine(但您可能也需要一个后台线程)。@TheLastError您对目标框架有任何限制吗?3.5/4.0/4.5? 如果不是这样的话,虽然我很感谢你接受我的回答,但我个人认为,
QtX
应该得到这一点上的分数。他/她的回答是例外的@Dayan:最新版本和往常一样。@Nicolamasatti:我不知道怎么做。你可以使用
ReadToEnd()
直到最后才会返回。。。相反,请尝试ReadLine(但您可能也需要一个后台线程)。@TheLastError您对目标框架有任何限制吗?3.5/4.0/4.5? 如果不是这样的话,虽然我很感谢你接受我的回答,但我个人认为,
QtX
应该得到这一点上的分数。他/她的回答是例外的@大雁:最新版本和往常一样。用
TextBox替换
Console.WriteLine
。Text
不起作用。由于对UI组件的跨线程访问,我将抛出
invalidoOperationException
。@QtX很好,在这种情况下,OP可以返回一个字符串列表,然后他可以迭代填充文本框。或者在消息传入时使用代理填充文本框。谢谢您指出这一点。@QtX用更改更新我的答案。用
TextBox替换
Console.WriteLine
。Text
不起作用。由于对UI组件的跨线程访问,我将抛出
invalidoOperationException
。@QtX很好,在这种情况下,OP可以返回一个字符串列表,然后他可以迭代填充文本框。或者在消息传入时使用代理填充文本框。谢谢你指出这一点。@QtX用更改更新了我的答案。答案很好,喜欢使用
async/await
。答案很好,喜欢使用
async/await