C'est peut-être une sorte de travail supplémentaire, mais j'irais dans l'autre sens.
Instanciez un TraceListener
pour la console et un pour le fichier journal; utilisez ensuite des Trace.Write
instructions dans votre code au lieu de Console.Write
. Il devient plus facile par la suite de supprimer le journal, ou la sortie de la console, ou d'attacher un autre mécanisme de journalisation.
static void Main(string[] 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 me souvienne, vous pouvez définir les écouteurs dans la configuration de l'application permettant d'activer ou de désactiver la journalisation sans toucher à la construction.
Il s'agit d'une classe simple qui sous-classe TextWriter pour permettre la redirection de l'entrée vers 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(string 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; } } }
la source
Console.WriteLine()
, ce qui était exactement ce que je voulais.Console.SetOut(doubleWriter);
. Ce qui modifie un global pour Console, cela m'a pris un peu, car je suis tellement habitué à travailler dans des applications où pratiquement rien n'est global. Bon produit!Découvrez log4net . Avec log4net, vous pouvez configurer des appenders de console et de fichier qui peuvent générer des messages de journal aux deux endroits avec une seule instruction de journal.
la source
Ne pouvez-vous pas simplement rediriger la sortie vers un fichier à l'aide de la
>
commande?Si vous avez besoin de mettre en miroir, vous pouvez essayer de trouver une version win32 de
tee
qui divise la sortie en un fichier.Voir /superuser/74127/tee-for-windows pour exécuter le tee à partir de PowerShell
la source
Vous pouvez sous-classer la classe TextWriter, puis affecter son instance à Console.Out à l'aide de la méthode Console.SetOut - qui fait en particulier la même chose que de transmettre la même chaîne aux deux méthodes dans la méthode de journal.
Une autre façon pourrait 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
la source
EDIT: Cette méthode offre la possibilité de rediriger les informations de la console provenant d'un package tiers. remplacer la méthode WriteLine est bon pour ma situation, mais vous devrez peut-être remplacer d'autres méthodes d'écriture en fonction du package tiers.
Nous devons d'abord créer une nouvelle classe inhérente à StreamWriter, disons CombinedWriter;
Puis lancez un nouvel instant de CombinedWriter avec Console.Out;
Enfin, nous pouvons rediriger la sortie de la console vers l'instant de la nouvelle classe par Console.SetOut;
Le code suivant est la nouvelle classe qui fonctionne pour moi.
public class CombinedWriter : StreamWriter { TextWriter console; public CombinedWriter(string 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 WriteLine(string value) { console.Write(value); base.WriteLine(value); } }
la source
public override void Write(char value);
,public override void Write(char[] buffer);
,public override void Write(string value);
etpublic override void Write(char[] buffer, int index, int count);
. Sinon, il ne s'imprime pas sur la console si vous utilisezWriteLine(format, ...)
method.Log4net peut le faire pour vous. Vous n'écririez que quelque chose comme ceci:
logger.info("Message");
Une configuration déterminera si l'impression ira à la console, au fichier ou aux deux.
la source
Je pense que ce que vous utilisez déjà est en quelque sorte la meilleure approche. Une méthode simple pour refléter essentiellement votre sortie.
Déclarez d'abord un TextWriter global au début:
private TextWriter txtMirror = new StreamWriter("mirror.txt");
Ensuite, créez une méthode pour écrire:
// Write empty line private void Log() { Console.WriteLine(); txtMirror.WriteLine(); } // Write text private void Log(string strText) { Console.WriteLine(strText); txtMirror.WriteLine(strText); }
Maintenant, au lieu d'utiliser
Console.WriteLine("...");
, utilisezLog("...");
. 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 sinon fonctionne bien, je l'utilise moi-même aussi!ÉDITER
Bien sûr, vous pouvez créer une méthode de
Console.Write();
la même manière si vous n'utilisez pas uniquement WriteLinesla source
Comme suggéré par Arul, l'utilisation
Console.SetOut
peut être utilisée pour rediriger la sortie vers un fichier texte:Console.SetOut(new StreamWriter("Output.txt"));
la source
La décision d'utiliser une classe, héritée du StreamWriter, des suggestions de l'utilisateur Keep Thinking, fonctionne. Mais j'ai dû ajouter dans la base du constructeur.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é avant qu'il n'enregistre toutes les données.
Je l'utilise comme:
CombinedWriter cw = new CombinedWriter ( "out.txt", true, Encoding.Unicode, 512, Console.Out ); Console.SetOut (cw);
la source
Merci à Keep Thinking pour l'excellente solution! J'ai ajouté d'autres remplacements pour éviter de consigner certains événements d'écriture de console qui (pour mes besoins) ne sont attendus que 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(string path, bool append, TextWriter consoleout) : base(path, append) { this.console = consoleout; base.AutoFlush = true; } public override void Write(string 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(string value) { console.WriteLine(value); if (value != "") { base.WriteLine(value); } } public new void Dispose() { base.Dispose(); } } class Program { static void Main(string[] 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(); } } }
la source
Si vous dupliquez la sortie de la console à partir d'un code que vous ne contrôlez pas, par exemple une bibliothèque tierce, tous les membres de TextWriter doivent être écrasé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 } }
ConsoleMirroring class
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 string 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(string 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(string format, params object[] arg) { _consoleOutput.Write(format, arg); _streamWriter.Write(format, arg); } public override void Write(string format, object arg0) { _consoleOutput.Write(format, arg0); _streamWriter.Write(format, arg0); } public override void Write(string 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(string 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(string 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(string format, params object[] arg) { _consoleOutput.WriteLine(format, arg); _streamWriter.WriteLine(format, arg); } public override void WriteLine(string format, object arg0) { _consoleOutput.WriteLine(format, arg0); _streamWriter.WriteLine(format, arg0); } public override void WriteLine(string 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(string 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); } } }
la source
Vous pouvez en fait 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!
la source
Ma réponse est basée sur la réponse non acceptée la plus votée , ainsi que sur la réponse la moins votée qui, à mon avis, est la solution la plus élégante à ce jour. C'est un peu plus générique en termes de type de flux que vous pouvez utiliser (vous pouvez utiliser un
MemoryStream
par exemple), mais j'ai omis toutes les fonctionnalités étendues incluses dans cette dernière réponse par souci de concision.class ConsoleMirrorWriter : TextWriter { private readonly StreamWriter _writer; private readonly TextWriter _consoleOut; public ConsoleMirrorWriter(Stream stream) { _writer = new StreamWriter(stream); _consoleOut = Console.Out; Console.SetOut(this); } public override Encoding Encoding => _writer.Encoding; public override void Flush() { _writer.Flush(); _consoleOut.Flush(); } public override void Write(char value) { _writer.Write(value); _consoleOut.Write(value); } protected override void Dispose(bool disposing) { if (!disposing) return; _writer.Dispose(); Console.SetOut(_consoleOut); } }
Usage:
using (var stream = File.Create(Path.Combine(Path.GetTempPath(), AppDomain.CurrentDomain.FriendlyName))) using (var writer = new ConsoleMirrorWriter(stream)) { // Code using console output. }
la source