Как передать консоль на несколько потоков сразу в С#?

У меня есть программа, которая выводит Консоль и записывает ее в файл журнала, однако она больше не отображается в окне консоли. Есть ли способ сохранить его в окне, но также записать его в файл журнала?

Update:

appLogStream = new FileStream(logFile, FileMode.Append, FileAccess.Write, FileShare.Read);
TextWriter logtxtWriter = Console.Out;
logstrmWriter = new StreamWriter(appLogStream);
if(!console) Console.SetOut(logstrmWriter);
logstrmWriter.AutoFlush = true;
Console.WriteLine("Started at " + DateTime.Now);
Консоль

- это постоянный набор в классе. В основном он говорит, использует ли он консольное окно или нет (readline не вызывается и т.д., Если не в консоли).

Итак, есть ли способ написать как консоль, так и файл?

Ответ 1

Вы можете просто прочитать, что этот поток зарегистрировал его и распечатал.

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


О вашем обновлении я бы предложил вам обменять все Console на пользовательскую функцию ведения журнала, например. экземпляр MyLogger (код ниже). Который записывает ваш вывод на консоль и в файл журнала.

class MyLogger {
    private FileStream appLogStream;

    public MyLogger() {
        appLogStream = new FileStream(logFile, FileMode.Append, FileAccess.Write,
                                      FileShare.Read);
        appLogStream.WriteLine("Started at " + DateTime.Now);
    }

    public Write(string msg) {
        Console.Write(msg);
        appLogStream.Write(msg);
    }

    public WriteLine(string msg) {
        Console.WriteLine(msg);
        appLogStream.WriteLine(msg);
    }
}

Ответ 2

Я думаю, вы можете сделать что-то вроде этого:

 public class ConsoleDecorator : TextWriter
{
    private TextWriter m_OriginalConsoleStream;

    public ConsoleDecorator(TextWriter consoleTextWriter)
    {
        m_OriginalConsoleStream = consoleTextWriter;
    }

    public override void WriteLine(string value)
    {
        m_OriginalConsoleStream.WriteLine(value);

        // Fire event here with value
    }


    public static void SetToConsole()
    {
        Console.SetOut(new ConsoleDecorator(Console.Out));
    }
}

Вам придется "зарегистрировать" оболочку с вызовом ConsoleDecorator.SetToConsole(); После этого каждый вызов Console.WriteLine перейдет к настраиваемому методу, и там вы можете запустить событие и получить текст, написанный в других местах (например, журнал).

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

Ответ 3

Когда вы вызываете Console.SetOut, вы указываете, куда должна писать Консоль. Если вы этого не сделаете (то есть, как обычно используется Консоль), и вы вызываете Console.Write, он проверяет, есть ли у него выходной редактор, а если нет, задает его с помощью

   stream = OpenStandardOutput(256);

а затем

        Encoding encoding = Encoding.GetEncoding((int) Win32Native.GetConsoleOutputCP());
        writer = TextWriter.Synchronized(new StreamWriter(stream, encoding, 256, false) { HaveWrittenPreamble = true, AutoFlush = true });

Итак, вы должны иметь возможность делать то, что вы делаете сейчас, и если вы также хотите отбросить все до стандартных, как если бы вы не перенаправили консоль, вы можете создать свой собственный сценарий, используя поток, который вы открываете, используя Console.OpenStandardOutput. Win32Native, используемый в этом коде, является внутренним, поэтому у вас нет доступа к нему, но вы можете использовать Console.OutputEncoding для получения кодировки, которую он использует.

Что-то, что вы также можете попробовать, это использовать свойство Console.Out, чтобы получить и вставить на стандартный вывод TextWriter непосредственно перед вызовом SetOut. Затем вы можете просто использовать это для эха для стандартного вывода.