Перенаправить console.writeline из приложения Windows в строку

У меня есть внешняя dll, написанная на С#, и я изучил из документации сборок, что она записывает свои отладочные сообщения в Консоль, используя Console.WriteLine.

эта DLL записывает на консоль во время моего взаимодействия с пользовательским интерфейсом приложения, поэтому я не делаю вызовы DLL напрямую, но я бы захватил весь вывод консоли, поэтому, я думаю, мне нужно было инсталлировать в загрузке формы, а затем получить захваченный текст позже.

Я хотел бы перенаправить весь вывод на строковую переменную.

Я пробовал Console.SetOut, но его использование для перенаправления на строку непросто.

Ответ 1

Как вам кажется, вы хотите поймать вывод Console в реальном времени, я понял, что вы можете создать свою собственную реализацию TextWriter, которая запускает событие, когда a Write или WriteLine происходит на Console.

Писатель выглядит так:

    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;
    }

Если это приложение WinForm, вы можете настроить автора и использовать его события в Program.cs следующим образом:

    /// <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");
    }

Ответ 2

В основном это означает следующее:

var originalConsoleOut = Console.Out; // preserve the original stream
using(var writer = new StringWriter())
{
    Console.SetOut(writer);

    Console.WriteLine("some stuff"); // or make your DLL calls :)

    writer.Flush(); // when you're done, make sure everything is written out

    var myString = writer.GetStringBuilder().ToString();
}

Console.SetOut(originalConsoleOut); // restore Console.Out

Итак, в вашем случае вы должны установить это, прежде чем звонить в свою стороннюю DLL.

Ответ 3

Или вы можете его обернуть в вспомогательном методе, который принимает некоторый код в качестве аргумента, который запускает его, и возвращает строку, которая была напечатана. Обратите внимание, как мы грамотно обрабатываем исключения.

public string RunCodeReturnConsoleOut(Action code) 
{
  string result;
  var originalConsoleOut = Console.Out;
  try 
  {
    using (var writer = new StringWriter()) 
    {
      Console.SetOut(writer);
      code();
      writer.Flush();
      result = writer.GetStringBuilder().ToString();
    }
    return result;
  }
  finally 
  {
    Console.SetOut(originalConsoleOut); 
  }
}

Ответ 4

Вы также можете вызвать SetOut с помощью Console.OpenStandardOutput, это восстановит исходный выходной поток:

Console.SetOut(new StreamWriter(Console.OpenStandardOutput()));