Search code examples
c#system.diagnostics

Process.Start leaves streams empty


I have the code to run a console command/utility, monitor the live output using 'Debug.WriteLine' and write the final output to a log file when needed.

Edit: It does not work for Praatcon.exe an analysis command line utility. It can be downloaded from here . Just invoke praatcon.exe without argument, it should write on 'stdout' about the Usage. The code wont catch it.

The issue is, it works good for certain utilities and I can see the debug output as well as log in the file. But for certain utilities, I see empty commands, even though when I run those commands through a CMD window, I see the output. I am capturing both the streams Output and Error.

Can someone help me with this ?

Full code can be found here

Here is how I am trying to do it

Initialization of ProcessStartInfo

        var info = new ProcessStartInfo(command, parameters)
        {
            WorkingDirectory = workingDirectory,
            UseShellExecute = false,
            RedirectStandardOutput = true,
            RedirectStandardError = true,
            CreateNoWindow = true
        };

Running the process and initializing the string builders for output and error streams.

        var process = Process.Start(info);

        var output = new StringBuilder();
        var error = new StringBuilder();

Starting the tasks for Reading Streams

        var errorTask = process.StandardError.ReadLineAsync();

        var lineTask = process.StandardOutput.ReadLineAsync();

Here is my while loop to monitor the progress and write output to the Debug Output window when there is any available.

            while (process.HasExited == false)
            {
                if (lineTask.IsCompleted)
                {
                    output.AppendLine(lineTask.Result);

                    Debug.WriteLine(lineTask.Result);

                    lineTask = process.StandardOutput.ReadLineAsync();
                }

                if (errorTask.IsCompleted)
                {
                    error.AppendLine(errorTask.Result);

                    Debug.WriteLine(errorTask.Result);

                    errorTask = process.StandardError.ReadLineAsync();
                }

                errorTask.Wait(TimeSpan.FromMilliseconds(100.0));
                lineTask.Wait(TimeSpan.FromMilliseconds(100.0));
            }

After this, I am reading the streams further to see if there is anything left in there.

I get empty strings in output and error for one command. The only thing I get correct is the 'ExitCode'.

Please tell me if there is anything I am doing the wrong way.


Solution

  • As discussed on IRC, there was a possibility that the program you're calling may have been writing to a stream other than standard out or standard error. There are also streams with numbers 3-9 on Windows.

    This was not the case with the process you were calling. It was actually using the Win32 call 'WriteConsole', which seems to access the console directly.

    It would be possible to move the output back to stderr by preloading a DLL (DLL injection) but this is hackish, so as the source of the program is available, it's perhaps better to 'fix' it or submit a patch to the authors.