Mise en miroir de la sortie de la console dans un fichier

Dans une application de console C #, existe-t-il un moyen judicieux de mettre en miroir la sortie de la console dans un fichier texte?

Actuellement, je ne fais que transmettre la même chaîne à Console.WriteLine et à InstanceOfStreamWriter.WriteLine dans une méthode de journalisation.

Cela pourrait être une sorte de travail supplémentaire, mais j’irais dans l’autre sens.

Instanciez un TraceListener pour la console et un autre pour le fichier journal; utilisez Trace.Write instructions Trace.Write dans votre code au lieu de Console.Write . Il devient ensuite plus facile de supprimer le journal ou la sortie de la console ou de connecter un autre mécanisme de journalisation.

 static void Main(ssortingng[] args) { Trace.Listeners.Clear(); TextWriterTraceListener twtl = new TextWriterTraceListener(Path.Combine(Path.GetTempPath(), AppDomain.CurrentDomain.FriendlyName)); twtl.Name = "TextLogger"; twtl.TraceOutputOptions = TraceOptions.ThreadId | TraceOptions.DateTime; ConsoleTraceListener ctl = new ConsoleTraceListener(false); ctl.TraceOutputOptions = TraceOptions.DateTime; Trace.Listeners.Add(twtl); Trace.Listeners.Add(ctl); Trace.AutoFlush = true; Trace.WriteLine("The first line to be in the logfile and on the console."); } 

Pour autant que je puisse m’en souvenir, vous pouvez définir les écouteurs dans la configuration de l’application, ce qui permet d’activer ou de désactiver la journalisation sans toucher à la version.

Ceci est une classe simple qui sous-classe TextWriter pour permettre la redirection de l’entrée à la fois à un fichier et à la console.

Utilisez-le comme ça

  using (var cc = new ConsoleCopy("mylogfile.txt")) { Console.WriteLine("testing 1-2-3"); Console.WriteLine("testing 4-5-6"); Console.ReadKey(); } 

Voici la classe:

 class ConsoleCopy : IDisposable { FileStream fileStream; StreamWriter fileWriter; TextWriter doubleWriter; TextWriter oldOut; class DoubleWriter : TextWriter { TextWriter one; TextWriter two; public DoubleWriter(TextWriter one, TextWriter two) { this.one = one; this.two = two; } public override Encoding Encoding { get { return one.Encoding; } } public override void Flush() { one.Flush(); two.Flush(); } public override void Write(char value) { one.Write(value); two.Write(value); } } public ConsoleCopy(ssortingng path) { oldOut = Console.Out; try { fileStream = File.Create(path); fileWriter = new StreamWriter(fileStream); fileWriter.AutoFlush = true; doubleWriter = new DoubleWriter(fileWriter, oldOut); } catch (Exception e) { Console.WriteLine("Cannot open file for writing"); Console.WriteLine(e.Message); return; } Console.SetOut(doubleWriter); } public void Dispose() { Console.SetOut(oldOut); if (fileWriter != null) { fileWriter.Flush(); fileWriter.Close(); fileWriter = null; } if (fileStream != null) { fileStream.Close(); fileStream = null; } } } 

Découvrez log4net . Avec log4net, vous pouvez configurer des appenders de console et de fichier pouvant générer des messages de journalisation aux deux endroits avec une seule instruction de journal.

Vous pouvez sous-classer la classe TextWriter, puis atsortingbuer son instance à Console.Out à l’aide de la méthode Console.SetOut , qui fait notamment la même chose que de transmettre la même chaîne aux deux méthodes de la méthode log.

Une autre méthode consisterait à déclarer votre propre classe de console et à utiliser l’instruction using pour distinguer les classes:

 using Console = My.Very.Own.Little.Console; 

Pour accéder à la console standard, vous aurez alors besoin de:

 global::Console.Whatever 

Ne pouvez-vous pas simplement redirect la sortie vers un fichier en utilisant la commande > ?

 c:\>Console.exe > c:/temp/output.txt 

Si vous devez mettre en miroir, vous pouvez essayer de trouver une version win32 du tee qui divise la sortie en fichier.

Comme j’ai beaucoup appris ici, j’ai vraiment besoin de partager ma solution ici.

Nous devons d’abord créer une nouvelle classe inhérente à StreamWriter, par exemple CombinedWriter;

Ensuite, lancez un nouvel instant de CombinedWriter avec Console.Out;

Enfin, nous pouvons redirect la sortie de la console vers l’instant de la nouvelle classe par Console.SetOut;

Le code suivant est la nouvelle classe fonctionne pour moi.

 public class CombinedWriter : StreamWriter { TextWriter console; public CombinedWriter(ssortingng path, bool append, Encoding encoding, int bufferSize, TextWriter console) :base(path, append, encoding, bufferSize) { this.console = console; base.AutoFlush = true; // thanks for @konoplinovich reminding } public override void Write(ssortingng value) { console.Write(value); base.Write(value); } } 

Log4net peut le faire pour vous. Vous écrivez seulement quelque chose comme ceci:

 logger.info("Message"); 

Une configuration déterminera si l’impression ira à la console, au fichier ou aux deux.

Comme suggéré par Arul, vous pouvez utiliser Console.SetOut pour redirect la sortie vers un fichier texte:

 Console.SetOut(new StreamWriter("Output.txt")); 

Je pense que ce que vous utilisez déjà est la meilleure approche. Une méthode simple pour refléter essentiellement votre sortie.

Commencez par déclarer un TextWriter global au début:

 private TextWriter txtMirror = new StreamWriter("mirror.txt"); 

Ensuite, faites une méthode pour écrire:

 // Write empty line private void Log() { Console.WriteLine(); txtMirror.WriteLine(); } // Write text private void Log(ssortingng strText) { Console.WriteLine(strText); txtMirror.WriteLine(strText); } 

Maintenant, au lieu d’utiliser Console.WriteLine("..."); , utilisez Log("..."); . Aussi simple que cela. C’est encore plus court!


Il pourrait y avoir des problèmes si vous déplacez la position du curseur ( Console.SetCursorPosition(x, y); ), mais si ça marche bien, je l’utilise aussi!

MODIFIER

Bien sûr, vous pouvez créer une méthode pour Console.Write(); de la même manière si vous n’utilisez pas que WriteLines

La décision d’utiliser une classe, héritée de StreamWriter, des suggestions de l’utilisateur Keep Thinking, fonctionne. Mais je devais append un constructeur base.AutoFlush = true:

 { this.console = console; base.AutoFlush = true; } 

et un appel explicite au destructeur:

 public new void Dispose () { base.Dispose (); } 

Sinon, le fichier est fermé plus tôt qu’il n’a enregistré toutes les données.

Je l’utilise comme:

 CombinedWriter cw = new CombinedWriter ( "out.txt", true, Encoding.Unicode, 512, Console.Out ); Console.SetOut (cw); 

Merci de continuer à penser à l’excellente solution! J’ai ajouté des éléments de remplacement supplémentaires pour éviter que certains événements d’écriture de la console soient enregistrés (pour mes besoins) uniquement pour l’affichage de la console.

 using System; using System.IO; using System.Collections.Generic; using System.Linq; using System.Text; namespace RedirectOutput { public class CombinedWriter : StreamWriter { TextWriter console; public CombinedWriter(ssortingng path, bool append, TextWriter consoleout) : base(path, append) { this.console = consoleout; base.AutoFlush = true; } public override void Write(ssortingng value) { console.Write(value); //base.Write(value);//do not log writes without line ends as these are only for console display } public override void WriteLine() { console.WriteLine(); //base.WriteLine();//do not log empty writes as these are only for advancing console display } public override void WriteLine(ssortingng value) { console.WriteLine(value); if (value != "") { base.WriteLine(value); } } public new void Dispose() { base.Dispose(); } } class Program { static void Main(ssortingng[] args) { CombinedWriter cw = new CombinedWriter("combined.log", false, Console.Out); Console.SetOut(cw); Console.WriteLine("Line 1"); Console.WriteLine(); Console.WriteLine("Line 2"); Console.WriteLine(""); for (int i = 0; i < 10; i++) { Console.Write("Waiting " + i.ToString()); Console.CursorLeft = 0; } Console.WriteLine(); for (int i = 0; i < 10; i++) { Console.Write("Waiting " + i.ToString()); } Console.WriteLine(); Console.WriteLine("Line 3"); cw.Dispose(); } } } 

Vous pouvez créer une mise en miroir transparente de Console.Out to Trace en implémentant votre propre classe héritée de TextWriter et en remplaçant la méthode WriteLine.

Dans WriteLine, vous pouvez l’écrire dans Trace, qui peut ensuite être configuré pour écrire dans un fichier.

J’ai trouvé cette réponse très utile: https://stackoverflow.com/a/10918320/379132

Cela a fonctionné pour moi!

Si vous dupliquez une sortie de console à partir d’un code que vous ne contrôlez pas, par exemple une bibliothèque tierce, tous les membres de TextWriter doivent être remplacés. Le code utilise des idées de ce fil.

Usage:

 using (StreamWriter writer = new StreamWriter(filePath)) { using (new ConsoleMirroring(writer)) { // code using console output } } 

Classe ConsoleMirroring

 public class ConsoleMirroring : TextWriter { private TextWriter _consoleOutput; private TextWriter _consoleError; private StreamWriter _streamWriter; public ConsoleMirroring(StreamWriter streamWriter) { this._streamWriter = streamWriter; _consoleOutput = Console.Out; _consoleError = Console.Error; Console.SetOut(this); Console.SetError(this); } public override Encoding Encoding { get { return _consoleOutput.Encoding; } } public override IFormatProvider FormatProvider { get { return _consoleOutput.FormatProvider; } } public override ssortingng NewLine { get { return _consoleOutput.NewLine; } set { _consoleOutput.NewLine = value; } } public override void Close() { _consoleOutput.Close(); _streamWriter.Close(); } public override void Flush() { _consoleOutput.Flush(); _streamWriter.Flush(); } public override void Write(double value) { _consoleOutput.Write(value); _streamWriter.Write(value); } public override void Write(ssortingng value) { _consoleOutput.Write(value); _streamWriter.Write(value); } public override void Write(object value) { _consoleOutput.Write(value); _streamWriter.Write(value); } public override void Write(decimal value) { _consoleOutput.Write(value); _streamWriter.Write(value); } public override void Write(float value) { _consoleOutput.Write(value); _streamWriter.Write(value); } public override void Write(bool value) { _consoleOutput.Write(value); _streamWriter.Write(value); } public override void Write(int value) { _consoleOutput.Write(value); _streamWriter.Write(value); } public override void Write(uint value) { _consoleOutput.Write(value); _streamWriter.Write(value); } public override void Write(ulong value) { _consoleOutput.Write(value); _streamWriter.Write(value); } public override void Write(long value) { _consoleOutput.Write(value); _streamWriter.Write(value); } public override void Write(char[] buffer) { _consoleOutput.Write(buffer); _streamWriter.Write(buffer); } public override void Write(char value) { _consoleOutput.Write(value); _streamWriter.Write(value); } public override void Write(ssortingng format, params object[] arg) { _consoleOutput.Write(format, arg); _streamWriter.Write(format, arg); } public override void Write(ssortingng format, object arg0) { _consoleOutput.Write(format, arg0); _streamWriter.Write(format, arg0); } public override void Write(ssortingng format, object arg0, object arg1) { _consoleOutput.Write(format, arg0, arg1); _streamWriter.Write(format, arg0, arg1); } public override void Write(char[] buffer, int index, int count) { _consoleOutput.Write(buffer, index, count); _streamWriter.Write(buffer, index, count); } public override void Write(ssortingng format, object arg0, object arg1, object arg2) { _consoleOutput.Write(format, arg0, arg1, arg2); _streamWriter.Write(format, arg0, arg1, arg2); } public override void WriteLine() { _consoleOutput.WriteLine(); _streamWriter.WriteLine(); } public override void WriteLine(double value) { _consoleOutput.WriteLine(value); _streamWriter.WriteLine(value); } public override void WriteLine(decimal value) { _consoleOutput.WriteLine(value); _streamWriter.WriteLine(value); } public override void WriteLine(ssortingng value) { _consoleOutput.WriteLine(value); _streamWriter.WriteLine(value); } public override void WriteLine(object value) { _consoleOutput.WriteLine(value); _streamWriter.WriteLine(value); } public override void WriteLine(float value) { _consoleOutput.WriteLine(value); _streamWriter.WriteLine(value); } public override void WriteLine(bool value) { _consoleOutput.WriteLine(value); _streamWriter.WriteLine(value); } public override void WriteLine(uint value) { _consoleOutput.WriteLine(value); _streamWriter.WriteLine(value); } public override void WriteLine(long value) { _consoleOutput.WriteLine(value); _streamWriter.WriteLine(value); } public override void WriteLine(ulong value) { _consoleOutput.WriteLine(value); _streamWriter.WriteLine(value); } public override void WriteLine(int value) { _consoleOutput.WriteLine(value); _streamWriter.WriteLine(value); } public override void WriteLine(char[] buffer) { _consoleOutput.WriteLine(buffer); _streamWriter.WriteLine(buffer); } public override void WriteLine(char value) { _consoleOutput.WriteLine(value); _streamWriter.WriteLine(value); } public override void WriteLine(ssortingng format, params object[] arg) { _consoleOutput.WriteLine(format, arg); _streamWriter.WriteLine(format, arg); } public override void WriteLine(ssortingng format, object arg0) { _consoleOutput.WriteLine(format, arg0); _streamWriter.WriteLine(format, arg0); } public override void WriteLine(ssortingng format, object arg0, object arg1) { _consoleOutput.WriteLine(format, arg0, arg1); _streamWriter.WriteLine(format, arg0, arg1); } public override void WriteLine(char[] buffer, int index, int count) { _consoleOutput.WriteLine(buffer, index, count); _streamWriter.WriteLine(buffer, index, count); } public override void WriteLine(ssortingng format, object arg0, object arg1, object arg2) { _consoleOutput.WriteLine(format, arg0, arg1, arg2); _streamWriter.WriteLine(format, arg0, arg1, arg2); } protected override void Dispose(bool disposing) { if (disposing) { Console.SetOut(_consoleOutput); Console.SetError(_consoleError); } } }