简体   繁体   中英

Understanding how to control stdout using System.Diagnostics.Process

I see several questions about how to launch processes and push data into stdin, but not how to control where their output goes.

First here is my current code, run from a console mode C# application:

    // Prepare the process to run
    ProcessStartInfo start = new ProcessStartInfo();
    // Enter in the command line arguments, everything you would enter after the executable name itself
    start.Arguments = " -";
    // Enter the executable to run, including the complete path
    start.FileName = "doxygen.exe";
    // Do you want to show a console window?
    start.WindowStyle = ProcessWindowStyle.Normal;
    start.CreateNoWindow = false;
    start.RedirectStandardInput = true;
    start.UseShellExecute = false;

    // Run the external process & wait for it to finish
    using (Process proc = Process.Start(start))
    {
        //doxygenProperties is just a dictionary
        foreach (string key in doxygenProperties.Keys)
            proc.StandardInput.WriteLine(key+" = "+doxygenProperties[key]);
        proc.StandardInput.Close();
        proc.WaitForExit();

        // Retrieve the app's exit code
        int exitCode = proc.ExitCode;
    }

What happens when I run this is I do not see any new window (though I think I should) and all of doxygen.exe's stdout is printed to my app's console window.

What I would like to happen is one of two things:

  1. Doxygen is launched in a visible window, and I can see its stdout in that window, not in my app's window.
  2. Doxygen is launched in a hidden window, and it's stdout is written to a log file.

How can I achieve these?

In addition, why am I not getting a separate window for the spawned process, and why is the spawned process writing output to my window not its own?

One thing that you can do is use RedirectStandardOutput and instead of using WaitForExit you can use ReadToEnd

ProcessStartInfo start = new ProcessStartInfo();
start.RedirectStandardOutput = true;

//make other adjustments to start

Process p = new Process();
p.StartInfo = start;
p.Start();
string output = p.StandardOutput.ReadToEnd();

and then you can use string output at your leisure


If you want to get output in real-time the p.StandardOutput property has methods that allow you to get the output asynchronously. I don't know all the details to it offhand, I've only used it once before, but there's plenty of literature out there if you search for it.


Also be careful when redirecting both StandardOutput and StandardError at the same time, If they're long enough, it is possible for that to cause deadlocks.

You need to do two things:

1) Indicate that you want the standard output of the process to be directed to your app by setting the RedirectStandardOuput property to true in the process.

2) BEFORE the call to WaitForExit , start capturing the output:

string sOutput = p.StandardOutput.ReadToEnd();

If you do not start reading the output before calling wait for exit, you can encounter a deadlock.

However, it is important to know that standard output will only capture output information, not anything written to the standard error stream of the app.

In order to capture both streams of information, you can hook the process's OutputDataReceived and ErrorDataReceived events and write the event data directly into a log file or store it in a class property for use after the process has completed.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM