Recipe8.14.Capturing Standard Output for a Process


Recipe 8.14. Capturing Standard Output for a Process

Problem

You need to be able to capture standard output for a process you are launching.

Solution

Use the RedirectStandardOutput property of the Process.StartInfo class to capture the output from the process. By redirecting the standard output stream of the process, you read it when the process terminates. UseShellExecute is a property on the ProcessInfo class that tells the runtime whether or not to use the Windows shell to start the process or not. By default, it is turned on (true) and the shell runs the program, which means that the output cannot be redirected. This needs to be set to off and then the redirection can occur. The UseShellExecute property is set to false to ensure this is not started using the Windows shell for your purposes here.

In this example, a Process object for cmd.exe is set up with arguments to perform a directory listing, and then the output is redirected. A logfile is created to hold the resulting output and the Process.Start method is called.

 // See 12.21 for more info on redirection… Process application = new Process(); // Run the command shell. application.StartInfo.FileName = @"cmd.exe"; // Get a directory listing from the current directory. application.StartInfo.Arguments = @"/Cdir " + Environment.CurrentDirectory; Console.WriteLine("Running cmd.exe with arguments: {0}",                 application.StartInfo.Arguments); // Redirect standard output so we can read it. application.StartInfo.RedirectStandardOutput = true; application.StartInfo.UseShellExecute = false; // Create a logfile to hold the results in the current EXE directory. using (StreamWriter logger = new StreamWriter("cmdoutput.log")) {     // Start it up.     application.Start(); 

Once the process is started, the StandardOutput stream can be accessed and a reference to it held. The code then reads in the information from the output stream while the application runs and writes it to the logfile that was set up previously. Once the application finishes, the logfile is closed.

 // Get stdout. StreamReader output = application.StandardOutput;   // Dump the output stream while the app runs. do {     using (output)     {         char[] info = null;         while (output.Peek() >= 0)         {             info = new char[4096];             output.Read(info, 0, info.Length);             // Write to the logger.             logger.Write(info, 0, info.Length);         }     } } while (!application.HasExited); } // Close the process object. application.Close(); 

cmdoutput.log holds information similar to the following output:

 Volume in drive C has no label.  Volume Serial Number is DDDD-FFFF  Directory of C:\C#Cookbook2\Code\CSharpRecipes\bin\Debug  08/28/2005 12:25 PM <DIR>        .  08/28/2005 12:25 PM <DIR>        ..  08/28/2005 12:25 PM                  0 cmdoutput.log  08/15/2005 09:46 PM            489,269 CSharpCookbook.zip  08/28/2005 12:24 PM            450,560 CSharpRecipes.exe  08/28/2005 12:24 PM          1,031,680 CSharpRecipes.pdb  07/22/2005 08:28 AM              5,120 CSharpRecipes.vshost.exe  04/12/2005 10:15 PM                432 CSharpRecipes.vshost.xml  05/10/2005 10:14 PM                998 CSharpRecipes.vshost.xsd  03/29/2005 10:27 AM                432 CSharpRecipes.xml  05/10/2005 10:14 PM                998 CSharpRecipes.xsd  03/29/2005 10:27 AM                155 data.txt  04/12/2005 10:15 PM                134 HT.data  12/10/2003 10:11 PM             12,288 REGEX_Test.dll  08/20/2005 09:27 PM             16,384 SampleClassLibrary.dll  08/20/2005 09:27 PM             11,776 SampleClassLibrary.pdb  08/02/2005 08:56 PM                483 se1.object  08/02/2005 08:56 PM                480 se2.object  08/02/2005 08:56 PM                767 se3.object  08/02/2005 08:56 PM                488 se4.object  08/02/2005 08:56 PM                775 se5.object  04/12/2005 10:15 PM              1,369 TEST.DATA  04/12/2005 10:14 PM                327 TestBinSerXML.txt               21 File(s)       2,024,915 bytes                2 Dir(s)   98,005,683,712 bytes free 

Discussion

Redirecting standard output is a common task that can sometimes be of great use for tasks like automated build scenarios or test harnesses. While not quite as easy as simply placing > after the command line for a process at the command prompt, this approach is more flexible, as the stream output can be reformatted as XML or HTML for posting to a web site. This also provides the opportunity to send the data to multiple locations at once, which the simple command-line redirect function as provided by Windows is incapable of.

Waiting to read from the stream until the application has finished ensures that there will be no deadlock issues. If the stream is accessed synchronously before this time, then the possibility exists for the parent to block the child. At a minimum, the child will wait until the parent has finished reading from the stream before it continues writing to it. So by postponing the read until the end, you allow the child to have less performance degradation at the cost of some additional time at the end.

See Also

See Recipe 12.21; see the "ProcessStartInfo.RedirectStandardOutput Property" and "ProcessStartInfo.UseShellExecute Property" topics in the MSDN documentation.



C# Cookbook
Secure Programming Cookbook for C and C++: Recipes for Cryptography, Authentication, Input Validation & More
ISBN: 0596003943
EAN: 2147483647
Year: 2004
Pages: 424

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net