Redirect Console.Writeline from Windows Application to a String

Redirect console.writeline from windows application to a string

As it seems like you want to catch the Console output in realtime, I figured out that you might create your own TextWriter implementation that fires an event whenever a Write or WriteLine happens on the Console.

The writer looks like this:

    public class ConsoleWriterEventArgs : EventArgs
{
public string Value { get; private set; }
public ConsoleWriterEventArgs(string value)
{
Value = value;
}
}

public class ConsoleWriter : TextWriter
{
public override Encoding Encoding { get { return Encoding.UTF8; } }

public override void Write(string value)
{
if (WriteEvent != null) WriteEvent(this, new ConsoleWriterEventArgs(value));
base.Write(value);
}

public override void WriteLine(string value)
{
if (WriteLineEvent != null) WriteLineEvent(this, new ConsoleWriterEventArgs(value));
base.WriteLine(value);
}

public event EventHandler<ConsoleWriterEventArgs> WriteEvent;
public event EventHandler<ConsoleWriterEventArgs> WriteLineEvent;
}

If it's a WinForm app, you can setup the writer and consume its events in the Program.cs like this:

    /// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
using (var consoleWriter = new ConsoleWriter())
{
consoleWriter.WriteEvent += consoleWriter_WriteEvent;
consoleWriter.WriteLineEvent += consoleWriter_WriteLineEvent;

Console.SetOut(consoleWriter);
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}

static void consoleWriter_WriteLineEvent(object sender, Program.ConsoleWriterEventArgs e)
{
MessageBox.Show(e.Value, "WriteLine");
}

static void consoleWriter_WriteEvent(object sender, Program.ConsoleWriterEventArgs e)
{
MessageBox.Show(e.Value, "Write");
}

Redirect Console.WriteLine() output to string

Use a StringWriter:

var sw = new StringWriter();
Console.SetOut(sw);
Console.SetError(sw);
Console.WriteLine("Hello world.");
string result = sw.ToString();

Redirecting Console.WriteLine() to Textbox

Start by creating a new TextWriter that is capable of writing to a textbox. It only needs to override the Write method that accepts a char, but that would be ungodly inefficient, so it's better to overwrite at least the method with a string.

public class ControlWriter : TextWriter
{
private Control textbox;
public ControlWriter(Control textbox)
{
this.textbox = textbox;
}

public override void Write(char value)
{
textbox.Text += value;
}

public override void Write(string value)
{
textbox.Text += value;
}

public override Encoding Encoding
{
get { return Encoding.ASCII; }
}
}

In this case I've had it just accept a Control, which could be a Textbox, a Label, or whatever. If you want to change it to just a Label that would be fine.

Then just set the console output to a new instance of this writer, pointing to some textbox or label:

Console.SetOut(new ControlWriter(textbox1));

If you want the output to be written to the console as well as to the textbox we can use this class to create a writer that will write to several writers:

public class MultiTextWriter : TextWriter
{
private IEnumerable<TextWriter> writers;
public MultiTextWriter(IEnumerable<TextWriter> writers)
{
this.writers = writers.ToList();
}
public MultiTextWriter(params TextWriter[] writers)
{
this.writers = writers;
}

public override void Write(char value)
{
foreach (var writer in writers)
writer.Write(value);
}

public override void Write(string value)
{
foreach (var writer in writers)
writer.Write(value);
}

public override void Flush()
{
foreach (var writer in writers)
writer.Flush();
}

public override void Close()
{
foreach (var writer in writers)
writer.Close();
}

public override Encoding Encoding
{
get { return Encoding.ASCII; }
}
}

Then using this we can do:

Console.SetOut(new MultiTextWriter(new ControlWriter(textbox1), Console.Out));

redirect console output to text window in winform app

I think the proc.WaitForExit(); is your problem--it's a synchronous call that blocks until the process completes. That means nothing happens on the UI thread (including everything you've BeginInvoked) until the process is finished.

How to Save Console.WriteLine Output to Text File

Try this example from this article - Demonstrates redirecting the Console output to a file

using System;
using System.IO;

static public void Main ()
{
FileStream ostrm;
StreamWriter writer;
TextWriter oldOut = Console.Out;
try
{
ostrm = new FileStream ("./Redirect.txt", FileMode.OpenOrCreate, FileAccess.Write);
writer = new StreamWriter (ostrm);
}
catch (Exception e)
{
Console.WriteLine ("Cannot open Redirect.txt for writing");
Console.WriteLine (e.Message);
return;
}
Console.SetOut (writer);
Console.WriteLine ("This is a line of text");
Console.WriteLine ("Everything written to Console.Write() or");
Console.WriteLine ("Console.WriteLine() will be written to a file");
Console.SetOut (oldOut);
writer.Close();
ostrm.Close();
Console.WriteLine ("Done");
}

Writing output to the console from a c# winforms application

There are basically two things that can happen here.

  1. Console output

It is possible for a winforms program to attach itself to the console window that created it (or to a different console window, or indeed to a new console window if desired). Once attached to the console window Console.WriteLine() etc works as expected. One gotcha to this approach is that the program returns control to the console window immediately, and then carries on writing to it, so the user can also type away in the console window. You can use start with the /wait parameter to handle this I think.

Start commsnd syntax


  1. Redirected console output

This is when someone pipes the output from your program somewhere else, eg.

yourapp > file.txt

Attaching to a console window in this case effectively ignores the piping. To make this work you can call Console.OpenStandardOutput() to get a handle to the stream that the output should be piped to. This only works if the output is piped, so if you want to handle both of the scenarios you need to open the standard output and write to it and attach to the console window. This does mean that the output is sent to the console window and to the pipe but its the best solution I could find. Below the code I use to do this.

// This always writes to the parent console window and also to a redirected stdout if there is one.
// It would be better to do the relevant thing (eg write to the redirected file if there is one, otherwise
// write to the console) but it doesn't seem possible.
public class GUIConsoleWriter : IConsoleWriter
{
[System.Runtime.InteropServices.DllImport("kernel32.dll")]
private static extern bool AttachConsole(int dwProcessId);

private const int ATTACH_PARENT_PROCESS = -1;

StreamWriter _stdOutWriter;

// this must be called early in the program
public GUIConsoleWriter()
{
// this needs to happen before attachconsole.
// If the output is not redirected we still get a valid stream but it doesn't appear to write anywhere
// I guess it probably does write somewhere, but nowhere I can find out about
var stdout = Console.OpenStandardOutput();
_stdOutWriter = new StreamWriter(stdout);
_stdOutWriter.AutoFlush = true;

AttachConsole(ATTACH_PARENT_PROCESS);
}

public void WriteLine(string line)
{
_stdOutWriter.WriteLine(line);
Console.WriteLine(line);
}
}

What is a good way to direct console output to Text-box in Windows Form?

Create a text writer which writes to a text box:

    public class TextBoxWriter : TextWriter
{
TextBox _output = null;

public TextBoxWriter (TextBox output)
{
_output = output;
}

public override void Write(char value)
{
base.Write(value);
_output.AppendText(value.ToString());
}

public override Encoding Encoding
{
get { return System.Text.Encoding.UTF8; }
}
}

And redirect Console output to this writer:

        //...

public Form()
{
InitializeComponent();
}

private void Form_Load(object sender, EventArgs e)
{
Console.SetOut(new TextBoxWriter(txtConsole));
Console.WriteLine("Now redirecting output to the text box");
}

Redirect Console.Write... Methods to Visual Studio's Output Window While Debugging

Change application type to Windows before debugging. Without Console window, Console.WriteLine works like Trace.WriteLine. Don't forget to reset application back to Console type after debugging.



Related Topics



Leave a reply



Submit