OWASP O2 Platform Blog

API_ConsoleOut.cs – New and InProcess Capture of the Console Output

There are multiple scenarious where it is usefull to capture (via Lambda callbacks) the calls to Console.Write. Most solutions out there are based on using the Process class (via its ProcessStartInfo settings):

The problem with those solutions is they are able to capture the Console Output of the new process created, NOT the current process (which is what I want since I need to see the Console messages created by an external API/Code that I consuming from O2)

Using O2 to captute Console Output of new processes

Note: If all you want to do is to capture the console output of a new process, there are a bunch of O2 methods/APIs that can help you with it:

Which can be used like this:

run cmd.exe (with params: /c dir) and get its console output

return "cmd.exe".startProcess_getConsoleOut(" /c dir");

run netstat.exe (with params: -na) and redirect its console into a lambda method

"netstat.exe".startProcess("-na", (line)=> line.info());

run netstat.exe and show its results in a table list

var topPanel = panel.clear().add_Panel();
var tableList = topPanel.add_TableList();
var lines = "netstat.exe".startProcess_getConsoleOut("-na")
                         .lines()
                         .removeRange(0,2);
var netstatData = (from line in lines
                   let fragments = line.split(" ").removeEmpty()
                   select new {
                                   @Type = fragments.value(0) , 
                                   Local_Address = fragments.value(1) ,
                                   Foreign_Address = fragments.value(2) ,
                                   State = fragments.value(3)
                                  });                  
tableList.show(netstatData);

Using O2 to captute Console Output in the current Process

To capture the Console Output in the current process, I first tried to capture the usage of a MemoryStream in a way simular to how Console actually works (see O2 blog post Dynamically creating private/internal types and delegates (UserCallBack and AsyncStreamReader) ) , but a much easier way is to specify a TextWriter via Console.SetOut.

To make it easier to use, I created the API_ConsoleOut class which can be used like this:

Show Console Ouput in a new window

"Write this to the console :)".open_ConsoleOut();
Console.Write("another");
Console.WriteLine("test");
//O2File:API_ConsoleOut.cs

Which looks like this:

 Show Console Output in an existing panel/control

var topPanel = panel.clear().add_Panel();
topPanel.show_ConsoleOut(); //this will open as a child of an existing control
Console.Write("another ");
Console.WriteLine("test");
topPanel.insert_Right().add_SourceCodeViewer().set_Text("<h1>some html<h1>",".html");
Console.WriteLine("now inside a Windows Control");

return "done";
//O2File:API_ConsoleOut.cs

Which looks like this:

 

Test GUI with Console Input

If you want to test the Console Input and Output, there is also a test GUI that you can use

var apiConsoleOut = new API_ConsoleOut();
apiConsoleOut.show_ConsoleOut_TestGui();

Console.Write("another ");
Console.WriteLine("test");
Console.WriteLine("now with more options");

//O2File:API_ConsoleOut.cs

Which looks like this:

Source code of API_Console_Out.cs

using System;
using System.IO;
using System.Text;
using System.Drawing;
using System.Windows.Forms;
using System.Collections.Generic;
using O2.Interfaces.O2Core;
using O2.Kernel;
using O2.Kernel.ExtensionMethods;
using O2.DotNetWrappers.ExtensionMethods;
using O2.Views.ASCX.classes.MainGUI;
using O2.XRules.Database.Utils;

//O2File:_Extra_methods_Misc.cs
//O2File:_Extra_methods_Windows.cs
//O2File:_Extra_methods_WinForms_Controls.cs

namespace O2.XRules.Database.APIs
{
    public class API_ConsoleOut : Control
    {            
        public O2StreamWriter o2StreamWriter;
       
        public API_ConsoleOut()
        {       
            this.o2StreamWriter = new O2StreamWriter();     
            this.o2StreamWriter.Name = "API_ConsoleOut";
            Console.SetOut(this.o2StreamWriter); 
        }
    }
   
    public class O2StreamWriter : TextWriter
    {
        public StringBuilder ConsoleOut     { get; set; }
        public StringBuilder CurrentLine    { get; set; }
        public List<string> Lines            { get; set; }
        public Action<char> On_NewChar        { get; set; }   
        public Action<string> On_NewLine     { get; set; }
        public bool LogAllChars                { get; set; }
        public bool LogAllLines                { get; set; }
        public string Name                    { get; set; }
        public int PauseBetweenCharWrite    { get; set; }
       
        public O2StreamWriter()
        {
            ConsoleOut = new StringBuilder();
            CurrentLine = new StringBuilder();
            Lines = new List<string>();       
            LogAllChars = false;
            LogAllLines = true;
            Name = "O2StreamWriter";
        }
   
        public override void Write(char value)
        {
            base.Write(value);
              this.ConsoleOut.Append(value.ToString());             
             
              if (value == '\n')
                  handleLine();                 
              else
                  this.CurrentLine.Append(value.ToString());
                 
              if (this.LogAllChars)
                "[{0}] char: {1}".info(this.Name, value);
           
            if (this.On_NewChar.notNull())
                this.On_NewChar(value);
           
            if (PauseBetweenCharWrite > 0)
                this.sleep(PauseBetweenCharWrite, false);
        }               
       
        public void handleLine()
        {
            var line = this.CurrentLine.str();
            if (line.lastChar('\r'))
                line = line.removeLastChar();
            this.CurrentLine = new StringBuilder();
            this.Lines.add(line);
           
            if (this.LogAllLines)
                "[{0}]: {1}".info(this.Name, line);
               
            if (this.On_NewLine.notNull())
                this.On_NewLine(line);           
        }
        public override Encoding Encoding
        {
            get { return System.Text.Encoding.UTF8; }
        }
    }
   
    public static class API_ConsoleOut_ExtensionMethods_TestGuis
    {
       
        public static API_ConsoleOut show_ConsoleOut_TestGui(this API_ConsoleOut apiConsoleOut)
        {
            var topPanel = O2Gui.open<Panel>("Console.Out capture Test",700,200);
            return apiConsoleOut.show_ConsoleOut_TestGui(topPanel);
        }
       
       
        public static API_ConsoleOut show_ConsoleOut_TestGui(this API_ConsoleOut apiConsoleOut, Control topPanel)
        {
            var consoleIn = topPanel.insert_Above(40, "ConsoleIn");
            var lines_TextBox = topPanel.clear().add_GroupBox("Console.Out Lines").add_TreeView();
            var chars_TextBox = topPanel.insert_Right("Console.Out Chars").add_TextArea();
                       
            consoleIn.add_TextBox("Write to send to Console Input ->","")
                     .onKeyPress_getChar( (_char)=> { if (_char == '\x0d') Console.WriteLine(); else  Console.Write(_char); })
                     .multiLine(true)
                     .focus();
                                
            apiConsoleOut.o2StreamWriter.On_NewChar = (_char) => chars_TextBox.append_Text(_char.str());
            apiConsoleOut.o2StreamWriter.On_NewLine = (line) => lines_TextBox.add_Node(line);
           
            //apiConsoleOut.o2StreamWriter.PauseBetweenCharWrite = 1;            
           
            Console.WriteLine("Welcome to show_ConsoleOut_TestGui");   
            Console.Write("Type something on the TextBox above to see it here".line());
            return apiConsoleOut;
        }
       
        public static API_ConsoleOut open_ConsoleOut(this string message)
        {
            return message.show_ConsoleOut();
        }
       
        public static API_ConsoleOut show_ConsoleOut(this string message)
        {
            var apiConsoleOut = new API_ConsoleOut();
            apiConsoleOut.show_ConsoleOut();
            Console.WriteLine(message);
            return apiConsoleOut;
        }
       
        public static API_ConsoleOut add_ConsoleOut(this Control topPanel)
        {
            return topPanel.show_ConsoleOut();
        }
       
        public static API_ConsoleOut show_ConsoleOut<T>(this T topPanel)
            where T : Control
        {
            return topPanel.show_ConsoleOut("Welcome to O2's console");
        }
       
        public static API_ConsoleOut show_ConsoleOut<T>(this T topPanel, string message )
            where T : Control
        {
            var apiConsoleOut = new API_ConsoleOut();
            apiConsoleOut.show_ConsoleOut(topPanel);
            Console.WriteLine(message);
            return apiConsoleOut;
        }
       
        public static API_ConsoleOut show_ConsoleOut(this API_ConsoleOut apiConsoleOut)
        {
            var topPanel = O2Gui.open<Panel>("Console.Out",700,200);
            return apiConsoleOut.show_ConsoleOut(topPanel);
        }
       
       
        public static API_ConsoleOut show_ConsoleOut(this API_ConsoleOut apiConsoleOut, Control topPanel)
        {
            var consoleOut = topPanel.add_TextArea();
            consoleOut.backColor(Color.Black);
            consoleOut.foreColor(Color.White);
            consoleOut.font("Lucida Console");
            apiConsoleOut.o2StreamWriter.On_NewChar = (_char) => consoleOut.append_Text(_char.str());
            apiConsoleOut.o2StreamWriter.LogAllLines = false;
           
            consoleOut.add_ContextMenu()
                      .add_MenuItem("Clear", false, ()=> consoleOut.set_Text(""))
                      .add_MenuItem("Write to Console Input", ()=> Console.WriteLine("Text to send to Console.Input".askUser()));
            return apiConsoleOut;
        }
    }
}

November 26, 2011 - Posted by | .NET, Tools

3 Comments »

  1. […] tuning the API_ConsoleOut (using a RichTextBox instead of a TextBox), I found a really weird behaviour with the […]

    Pingback by Weird Bug with RichTextBox’s ScrollToCaret while using AppendText (trying to fix text flickering) « OWASP O2 Platform Blog | November 27, 2011 | Reply

  2. […] tuning the API_ConsoleOut (using a RichTextBox instead of a TextBox), I found a really weird behaviour with the […]

    Pingback by Weird Bug with RichTextBox’s ScrollToCaret while using AppendText (trying to fix text flickering) « OWASP O2 Platform Blog | November 27, 2011 | Reply

  3. […] Article Source: API_ConsoleOut.cs – InProcess Capture of the Console Output. […]

    Pingback by API_ConsoleOut.cs – InProcess Capture of the Console Output | Code to Preload | November 27, 2011 | Reply


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: