同步捕获进程的输出(即"当它发生时")

joh*_*ahl 20 .net c#

我正在尝试启动一个进程并捕获输出,已经走了很远的路,但我还没有达到我想要的解决方案.

具体来说,我试图从我正在编写的小型实用程序应用程序重置我的开发机器上的IIS.我通过实验得出结论,安全的方法是通过iisreset.exe在子进程中运行.

如果iisreset.exe在命令提示符下运行,则会在此过程中收到反馈.运行iisreset需要几秒钟,并且会生成几行反馈,其间会有暂停.

我想捕获这些反馈并将其呈现在我的Windows窗体应用程序中(在a中ListBox),我已经成功了.我仍然担心的是,在子进程完成之前我不会得到它.我想在创建行时立即逐行获取子进程的输出.

我曾尝试做我的作业,阅读/测试例如:

还有几个内容相似的.大多数(全部?)异步获取输出(例如Process.ReadToEnd()).我希望输出同步,根据MSDN文档涉及建立一个事件处理程序等我已经尝试过.它可以工作,但在进程退出之前不会调用事件处理程序.我从iisreset.exe获取输出,但直到它完成.

为了排除这与iisreset.exe特别有关的可能性,我写了一个小的控制台应用程序,它生成一些输出,暂停之间:

namespace OutputGenerator
{
    class Program
    {
        static void Main(string[] args)
        {
            System.Console.WriteLine("OutputGenerator starting and pausing for 10 seconds..");
            System.Threading.Thread.Sleep(10000);
            System.Console.WriteLine("Pausing for another 10 seconds..");
            System.Threading.Thread.Sleep(10000);
            System.Console.WriteLine("Exiting!");
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

用这个测试结果证明我在需要时可以直接获取捕获的数据.因此,在某种程度上,似乎iisreset.exe输出数据的方式在这里发挥作用.

以下是执行捕获的程序代码(Windows窗体应用程序):

using System;
using System.Windows.Forms;
using System.Diagnostics; 

namespace OutputCapturer
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void btnRun_Click(object sender, EventArgs e)
        {
            // Running this will show all output after the process has exited
            //String path = @"C:\Windows\system32\iisreset.exe";

            // Running this will show all output "when it happens"
            String path = @"C:\OutputGenerator.exe";

            var p = new Process();
            p.StartInfo.FileName = path;
            p.StartInfo.UseShellExecute = false;  // ShellExecute = true not allowed when output is redirected..
            p.StartInfo.RedirectStandardOutput = true;
            p.StartInfo.CreateNoWindow = true;
            p.OutputDataReceived += OutputDataReceived;
            p.Start();
            p.BeginOutputReadLine();
        }

        private delegate void OutputDataToTextboxDelegate(String s);

        void OutputDataToTextbox(String s)
        {
            tbxOutput.Text += s + Environment.NewLine;
            tbxOutput.Refresh();
        }

        private void OutputDataReceived(object sender, DataReceivedEventArgs e)
        {
            if (e.Data != null && e.Data.ToString() != "")
            {
                // Must run the update of the textbox in the same thread that created it..
                tbxOutput.Invoke(
                    new OutputDataToTextboxDelegate(OutputDataToTextbox), 
                    DateTime.Now.ToString() + ": " + e.Data.ToString()
                );
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

认为这是一个EOL编码问题(iisreset.exeapearing作为我的应用程序的一行输出)),我运行了一个调试会话.不.StandardOutput多次调用事件处理程序(每个输出行一次iisreset.exe),但是这些调用在进程退出后进入一次.

我很乐意,如果我能从iisreset.exe"当它发生时" 得到输出,那么我可以将它显示为进度指示.

我已经看到另一个具有相同/类似问题的线程, 来自进程输出的异步捕获不能正常工作,但没有解决方案.

我有点难过.

joh*_*ahl 0

对于我的具体情况,解决方案是摩西先生在上面的评论中建议的,即运行iisreset /stop后跟iisreset /start

我需要一个正确的答案,而不是评论,以便将其标记为我的“接受的答案”,所以这个答案更多的是行政性的,而不是新的贡献。功劳应该归功于摩西先生..:-)


归档时间:

查看次数:

6800 次

最近记录:

13 年,2 月 前