1

I'm working with a .NET console application that uses color and cursor position in the console that I want to redirect it's output to a tcp socket. Redirecting the text from this application is easy, I can do that no problem, but I also need to redirect the cursor position and colors for full effect, and as far as I can tell there's no built-in way for System.Console to do that.

However, I know that if I had access to the application's source code I could implement my own class to immitate System.Console such that I could replace any instance of Console. with MyConsole. and could then serialize all console calls and pass them out a tcp socket or any other stream.

So basically the .NET application has lots of console calls like:

Console.WriteLine("blah");
Console.ForegroundColor = ConsoleColor.Yellow;
Console.CursorLeft = 15;

If I had access to the source code I could write my own class like thus:

    class ConsoleWithTCP
{
    public const char CMD_INDICATOR = (char)01; //this is the ascii 'start of heading' character. I'll use it to denote the start and end of a console command
    public const char CMD_END_INDICATOR = (char)02; //this is the ascii 'start of text' character. I'll use it to denote the end of a console command

    public static void WriteLine(object obj) => WriteLine(obj.ToString());
    public static void WriteLine(string format, params object[] args) => WriteLine(String.Format(format, args));
    public static void WriteLine(string format, object arg0) => WriteLine(String.Format(format, arg0));
    public static void WriteLine() => Write(Console.Out.NewLine);
    public static void WriteLine(string line) => Write(line + Console.Out.NewLine);

    public static void Write(string format, object arg0) => Write(String.Format(format, arg0));
    public static void Write(string format, params object[] args) => Write(String.Format(format, args));
    public static void Write(object obj) => Write(obj.ToString());
    public static void Write(string content)
    {
        //escape any cmd_indicators
        string cmdReplace = CMD_INDICATOR + "CMD_INDICATOR:" + CMD_END_INDICATOR;
        content.Replace(CMD_INDICATOR.ToString(), cmdReplace);

        //escape any cmd_end_indicators
        cmdReplace = CMD_INDICATOR + "CMD_END_INDICATOR:" + CMD_END_INDICATOR;
        content.Replace(CMD_END_INDICATOR.ToString(), cmdReplace);

        Console.Write(content);
        //also write to a TCP stream or a file
    }

    public static void WriteCmd(string cmdName, string data = "")
    {
        //make sure the command and data contain no special characters
        if (   data.Contains(CMD_INDICATOR)
            || cmdName.Contains(CMD_INDICATOR)
            || data.Contains(CMD_END_INDICATOR)
            || cmdName.Contains(CMD_END_INDICATOR))
        {
            throw new InvalidDataException("The data string cannot contain an ascii character 01");
        }

        string cmd = CMD_INDICATOR + cmdName + ":" + data + CMD_END_INDICATOR;
        //write the serialized command to a TCP stream or a file
    }


    public static void Clear()
    {
        Console.Clear();
        WriteCmd("Clear");
    }

    public static ConsoleColor ForegroundColor
    {
        get { return Console.ForegroundColor; }
        set
        {
            Console.ForegroundColor = value;
            WriteCmd("ForegroundColor", value.ToString());
        }
    }


    public static int CursorLeft
    {
        get { return Console.CursorLeft;}
        set
        {
            Console.CursorLeft = value;
            WriteCmd("CursorLeft", value.ToString());
        }
    }
}

, you get the idea, and then just replace all System.Console references with ConsoleWithTCP instead, ie:

ConsoleWithTCP.WriteLine("blah");
ConsoleWithTCP.ForegroundColor = ConsoleColor.Yellow;
ConsoleWithTCP.CursorLeft = 15;

Is there a way I can force .NET to do this for me without having to modify source code?

ashbygeek
  • 759
  • 3
  • 20
  • You could try setting `Console.Out` to your custom output: https://msdn.microsoft.com/en-us/library/system.console.out(v=vs.110).aspx Not sure how to make the color thing work. – MarcinJuraszek Jan 29 '17 at 17:05
  • Nope, that's the same as a standard process output redirect. It will give me characters, but not colors or cursor position. – ashbygeek Jan 29 '17 at 17:10
  • 1
    Probably useful: http://stackoverflow.com/q/10860837/11683, http://stackoverflow.com/q/19215670/11683, http://stackoverflow.com/q/21081773/11683 – GSerg Jan 29 '17 at 17:54
  • 1
    You can use a using directive like `using Console = Namespace.ConsoleWithTCP;` but you'd have to add that to every file. There's no project-wide mechanism. – Mike Zboray Jan 29 '17 at 19:12
  • Hmm... I'll have to look at reflexil and mono.cecil more closely. The suggestion also led me to [this stackoverflow](http://stackoverflow.com/questions/25077830/replace-references-to-a-type-namespace-using-mono-cecil) that answers an almost identical scenario. – ashbygeek Jan 29 '17 at 23:26
  • @mikez if I had more control over the application's source I would definitely go with your suggestion. Unfortunately, I can only edit SOME of the applicable source code. Still, +1 for an excellent suggestion. – ashbygeek Jan 29 '17 at 23:29
  • Oh, @GSerg also +1 for leading me to more helpful solutions. Thanks a bunch! – ashbygeek Jan 29 '17 at 23:34

0 Answers0