Capture output of process synchronously (i.e. “when it happens”)

前端 未结 6 1420
灰色年华
灰色年华 2020-12-18 18:50

I am trying to start a process and capture the output, have come a far way, but am not quite at the solution I\'d want.

Specifically, I am trying to reset the IIS on

6条回答
  •  情书的邮戳
    2020-12-18 19:29

    Well, I tried a helper class that I know works: http://csharptest.net/browse/src/Library/Processes/ProcessRunner.cs

    ProcessRunner runner = new ProcessRunner("iisreset.exe");
    runner.OutputReceived += OutputDataReceived;
    runner.Start("/RESTART", "/STATUS");
    

    However, this still doesn't solve the problem with this specific executable. It seems that iisreset was written in such a way that this is not possible. Even running the following from the command line:

    iisreset.exe /RESTART /STATUS > temp.txt
    

    Still nothing is written to the text file 'temp.txt' until after all services have been restarted.

    As for your example code, I would recommend reading a post I wrote some time ago: How to use System.Diagnostics.Process correctly. Specifically you are not reading the std::err stream or redirecting and closing the std::in stream. This can cause very undesirable results in your program. You can look at the example wrapper class linked above for how to do it with the output events, or if you want to directly read the streams you need to use two of your own threads.

        static void Main()
        {
            ProcessStartInfo psi = new ProcessStartInfo(@"C:\Windows\system32\iisreset.exe", "/RESTART /STATUS");
            psi.CreateNoWindow = true;
            psi.UseShellExecute = false;
            psi.RedirectStandardError = true;
            psi.RedirectStandardOutput = true;
            psi.RedirectStandardInput = true;
    
            ManualResetEvent output_complete = new ManualResetEvent(false);
            ManualResetEvent error_complete = new ManualResetEvent(false);
    
            Process p = Process.Start(psi);
            new ReadOutput(p.StandardOutput, output_complete);
            new ReadOutput(p.StandardError, error_complete);
            p.StandardInput.Close();
    
            p.WaitForExit();
            output_complete.WaitOne();
            error_complete.WaitOne();
        }
    
        private class ReadOutput
        {
            private StreamReader _reader;
            private ManualResetEvent _complete;
    
            public ReadOutput(StreamReader reader, ManualResetEvent complete)
            {
                _reader = reader;
                _complete = complete;
                Thread t = new Thread(new ThreadStart(ReadAll));
                t.Start();
            }
    
            void ReadAll()
            {
                int ch;
                while(-1 != (ch = _reader.Read()))
                {
                    Console.Write((char) ch);
                }
                _complete.Set();
            }
        }
    

    I wrote this just to see if anything was coming through. Still got nothing until the end, so I think your just SOL on getting asynchronous output from iisreset.

提交回复
热议问题