Redirecting Output to the Text File C#

redirecting output to the text file c#

You can't redirect like that when you are starting the program like that. It requires a shell such as CMD.EXE to do that.

Instead, you need to set ProcessStartInfo.RedirectStandardOutput to a stream that you manage yourself.

There's an example here.

That example shows how to get the data that the console process creates via a StreamReader. For your requirement, you would read from that StreamReader and write to a FileStream output.

In case it's any help, here's a utility class I wrote years ago (for .Net 2) which might be instructive:

using System;
using System.IO;
using System.Threading;
using System.Diagnostics;
using System.Collections;
using System.Collections.Specialized;

namespace ProcessUtilities
{
/// <summary>
/// Encapsulates an executable program.
/// This class makes it easy to run a console app and have that app's output appear
/// in the parent console's window, and to redirect input and output from/to files.
/// </summary>
/// <remarks>
/// To use this class:
/// (1) Create an instance.
/// (2) Set the ProgramFileName property if a filename wasn't specified in the constructor.
/// (3) Set other properties if required.
/// (4) Call Run().
/// </remarks>

public class Executable
{
#region Constructor

/// <summary>Runs the specified program file name.</summary>
/// <param name="programFileName">Name of the program file to run.</param>

public Executable(string programFileName)
{
ProgramFileName = programFileName;

_processStartInfo.ErrorDialog = false;
_processStartInfo.CreateNoWindow = false;
_processStartInfo.UseShellExecute = false;
_processStartInfo.RedirectStandardOutput = false;
_processStartInfo.RedirectStandardError = false;
_processStartInfo.RedirectStandardInput = false;
_processStartInfo.WindowStyle = ProcessWindowStyle.Hidden;
_processStartInfo.Arguments = "";
}

/// <summary>Constructor.</summary>

public Executable(): this(string.Empty)
{
}

#endregion // Constructor

#region Public Properties

/// <summary>The filename (full pathname) of the executable.</summary>

public string ProgramFileName
{
get
{
return _processStartInfo.FileName;
}

set
{
_processStartInfo.FileName = value;
}
}

/// <summary>The command-line arguments passed to the executable when run. </summary>

public string Arguments
{
get
{
return _processStartInfo.Arguments;
}

set
{
_processStartInfo.Arguments = value;
}
}

/// <summary>The working directory set for the executable when run.</summary>

public string WorkingDirectory
{
get
{
return _processStartInfo.WorkingDirectory;
}

set
{
_processStartInfo.WorkingDirectory = value;
}
}

/// <summary>
/// The file to be used if standard input is redirected,
/// or null or string.Empty to not redirect standard input.
/// </summary>

public string StandardInputFileName
{
set
{
_standardInputFileName = value;
_processStartInfo.RedirectStandardInput = !string.IsNullOrEmpty(value);
}

get
{
return _standardInputFileName;
}
}

/// <summary>
/// The file to be used if standard output is redirected,
/// or null or string.Empty to not redirect standard output.
/// </summary>

public string StandardOutputFileName
{
set
{
_standardOutputFileName = value;
_processStartInfo.RedirectStandardOutput = !string.IsNullOrEmpty(value);
}

get
{
return _standardOutputFileName;
}
}

/// <summary>
/// The file to be used if standard error is redirected,
/// or null or string.Empty to not redirect standard error.
/// </summary>

public string StandardErrorFileName
{
set
{
_standardErrorFileName = value;
_processStartInfo.RedirectStandardError = !string.IsNullOrEmpty(value);
}

get
{
return _standardErrorFileName;
}
}

#endregion // Public Properties

#region Public Methods

/// <summary>Add a set of name-value pairs into the set of environment variables available to the executable.</summary>
/// <param name="variables">The name-value pairs to add.</param>

public void AddEnvironmentVariables(StringDictionary variables)
{
if (variables == null)
throw new ArgumentNullException("variables");

StringDictionary environmentVariables = _processStartInfo.EnvironmentVariables;

foreach (DictionaryEntry e in variables)
environmentVariables[(string)e.Key] = (string)e.Value;
}

/// <summary>Run the executable and wait until the it has terminated.</summary>
/// <returns>The exit code returned from the executable.</returns>

public int Run()
{
Thread standardInputThread = null;
Thread standardOutputThread = null;
Thread standardErrorThread = null;

_standardInput = null;
_standardError = null;
_standardOutput = null;

int exitCode = -1;

try
{
using (Process process = new Process())
{
process.StartInfo = _processStartInfo;
process.Start();

if (process.StartInfo.RedirectStandardInput)
{
_standardInput = process.StandardInput;
standardInputThread = startThread(new ThreadStart(supplyStandardInput), "StandardInput");
}

if (process.StartInfo.RedirectStandardError)
{
_standardError = process.StandardError;
standardErrorThread = startThread(new ThreadStart(writeStandardError), "StandardError");
}

if (process.StartInfo.RedirectStandardOutput)
{
_standardOutput = process.StandardOutput;
standardOutputThread = startThread(new ThreadStart(writeStandardOutput), "StandardOutput");
}

process.WaitForExit();
exitCode = process.ExitCode;
}
}

finally // Ensure that the threads do not persist beyond the process being run
{
if (standardInputThread != null)
standardInputThread.Join();

if (standardOutputThread != null)
standardOutputThread.Join();

if (standardErrorThread != null)
standardErrorThread.Join();
}

return exitCode;
}

#endregion // Public Methods

#region Private Methods

/// <summary>Start a thread.</summary>
/// <param name="startInfo">start information for this thread</param>
/// <param name="name">name of the thread</param>
/// <returns>thread object</returns>

private static Thread startThread(ThreadStart startInfo, string name)
{
Thread t = new Thread(startInfo);
t.IsBackground = true ;
t.Name = name;
t.Start();
return t;
}

/// <summary>Thread which supplies standard input from the appropriate file to the running executable.</summary>

private void supplyStandardInput()
{
// feed text from the file a line at a time into the standard input stream

using (StreamReader reader = File.OpenText(_standardInputFileName))
using (StreamWriter writer = _standardInput)
{
writer.AutoFlush = true;

for (;;)
{
string textLine = reader.ReadLine();

if (textLine == null)
break;

writer.WriteLine(textLine);
}
}
}

/// <summary>Thread which outputs standard output from the running executable to the appropriate file.</summary>

private void writeStandardOutput()
{
using (StreamWriter writer = File.CreateText(_standardOutputFileName))
using (StreamReader reader = _standardOutput)
{
writer.AutoFlush = true;

for (;;)
{
string textLine = reader.ReadLine();

if (textLine == null)
break;

writer.WriteLine(textLine);
}
}

if (File.Exists(_standardOutputFileName))
{
FileInfo info = new FileInfo(_standardOutputFileName);

// if the error info is empty or just contains eof etc.

if (info.Length < 4)
info.Delete();
}
}

/// <summary>Thread which outputs standard error output from the running executable to the appropriate file.</summary>

private void writeStandardError()
{
using (StreamWriter writer = File.CreateText(_standardErrorFileName))
using (StreamReader reader = _standardError)
{
writer.AutoFlush = true;

for (;;)
{
string textLine = reader.ReadLine();

if (textLine == null)
break;

writer.WriteLine(textLine);
}
}

if (File.Exists(_standardErrorFileName))
{
FileInfo info = new FileInfo(_standardErrorFileName);

// if the error info is empty or just contains eof etc.

if (info.Length < 4)
info.Delete();
}
}

#endregion // Private Methods

#region Private Fields

private StreamReader _standardError ;
private StreamReader _standardOutput ;
private StreamWriter _standardInput ;

private string _standardInputFileName;
private string _standardOutputFileName;
private string _standardErrorFileName;

ProcessStartInfo _processStartInfo = new ProcessStartInfo();

#endregion // Private Fields
}
}

C# Redirecting process results to a text file

The output redirection operator > is a feature of cmd.exe, not the operating system. The naive way to use it is hence to call cmd as so:

p.StartInfo.FileName = "cmd.exe";
startInfo.Arguments = "/C \"attrib.exe /S *.jpg > mypics.txt\"";

The proper way to redirect the output, however, is to first set StartInfo.RedirectStandardOutput to true (which you did), and then pipe the output from Process.StandardOutput to the file, as so:

using(StreamWriter file = new StreamWriter("mypics.txt")) {
p.StandardOutput.CopyTo(file);
}

Or, async version:

using(StreamWriter file = new StreamWriter("mypics.txt")) {
await p.StandardOutput.CopyToAsync(file);
}

Redirect a process's output to both a file and the console

Could use something like that

using System;
using System.Diagnostics;

namespace InteractWithConsoleApp
{
class Program
{
static void Main(string[] args)
{
ProcessStartInfo cmdStartInfo = new ProcessStartInfo();
cmdStartInfo.FileName = @"C:\Windows\System32\cmd.exe";
cmdStartInfo.RedirectStandardOutput = true;
cmdStartInfo.RedirectStandardError = true;
cmdStartInfo.RedirectStandardInput = true;
cmdStartInfo.UseShellExecute = false;
cmdStartInfo.CreateNoWindow = true;

Process cmdProcess = new Process();
cmdProcess.StartInfo = cmdStartInfo;
cmdProcess.ErrorDataReceived += cmd_Error;
cmdProcess.OutputDataReceived += cmd_DataReceived;
cmdProcess.EnableRaisingEvents = true;
cmdProcess.Start();
cmdProcess.BeginOutputReadLine();
cmdProcess.BeginErrorReadLine();

cmdProcess.StandardInput.WriteLine("ping google.com.ua"); //Execute ping google.com.ua
cmdProcess.StandardInput.WriteLine("exit"); //Execute exit.

cmdProcess.WaitForExit();
}

static void cmd_DataReceived(object sender, DataReceivedEventArgs e)
{
Console.WriteLine("Output from other process");
Console.WriteLine(e.Data);
}

static void cmd_Error(object sender, DataReceivedEventArgs e)
{
Console.WriteLine("Error from other process");
Console.WriteLine(e.Data);
}
}
}

How to save STDOUT outputs to a text file?

You can have .NET inform you when the process has exited and then read the output. Because, as detunized mentioned in his answer+comment, if you call reader.ReadToEnd() before it has completed, you won't get all the output. If you think of it, it's quite obvious - the data hasn't been produced yet, so how can you expect the reader to read it?

By using events you will not block the method that starts the thread which can be quite useful if you have a GUI application and don't want to freeze the user interface while the child process is running.

// tell it to raise events and hook up a callback to when it completes
process.EnableRaisingEvents = true;
process.Exited += process_Exited;
process.Start();

This method will be called when the process has completed:

void process_Exited(object sender, EventArgs e)
{
var process = (Process)sender;
using (var f = File.CreateText(@"..."))
{
f.WriteLine(process.StandardOutput.ReadToEnd());
}
}

How do i redirect input output to file instead of stdout?

you mean this?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
String s;
while ((s = Console.In.ReadLine())!= null)
{
Console.Out.WriteLine(s);
}
}
}
}


Related Topics



Leave a reply



Submit