Comment sauvegarder la sortie d'une application console

j'ai besoin de conseils sur la façon d'avoir mon application c# console afficher le texte à l'utilisateur par le biais de la sortie standard tout en étant en mesure d'y accéder plus tard. La fonctionnalité actuelle que je voudrais implémenter est de dumper la totalité du tampon de sortie vers un fichier texte à la fin de l'exécution du programme.

la solution de contournement que j'utilise alors que je ne trouve pas une approche plus propre est la sous-classe TextWriter en outrepassant les méthodes d'écriture pour qu'elles écrivent à la fois dans un fichier et appellent l'auteur stdout original. Quelque chose comme ceci:

public class DirtyWorkaround {
  private class DirtyWriter : TextWriter {
    private TextWriter stdoutWriter;
    private StreamWriter fileWriter;

    public DirtyWriter(string path, TextWriter stdoutWriter) {
      this.stdoutWriter = stdoutWriter;
      this.fileWriter = new StreamWriter(path);
    }

    override public void Write(string s) {
      stdoutWriter.Write(s);

      fileWriter.Write(s);
      fileWriter.Flush();
    }

    // Same as above for WriteLine() and WriteLine(string),
    // plus whatever methods I need to override to inherit
    // from TextWriter (Encoding.Get I guess).
  }

  public static void Main(string[] args) {
    using (DirtyWriter dw = new DirtyWriter("path", Console.Out)) {
      Console.SetOut(dw);

      // Teh codez
    }
  }
}

voir qu'il écrit et tire la chasse du fichier tout le temps. J'aimerais le faire seulement à la fin de l'exécution, mais je n'ai trouvé aucun moyen d'accéder au tampon de sortie.

aussi, excusez les inexactitudes avec le code ci-dessus (a dû l'écrire ad hoc, désolé ;).

10
demandé sur André Chalella 2008-09-14 07:50:10

6 réponses

La parfaite solution pour cela est d'utiliser log4net

5
répondu Mike Schall 2008-09-14 04:45:42

si vous voulez du code réutilisable, envisagez d'implémenter une classe appelée MultiWriter ou quelqu'un qui prend comme entrée deux (ou N?) TextWriter diffuse et distribue tous les writs, flushes,etc. à ces flux. Ensuite vous pouvez faire cette chose de fichier/console, mais tout aussi facilement vous pouvez diviser n'importe quel flux de sortie. Utile!

4
répondu Jason Cohen 2008-09-14 04:06:46

Probablement pas ce que vous voulez, mais juste au cas où... Apparemment, outils PowerShell une version du vénérable tee la commande. Qui est destiné à peu près exactement ce but. Si... la fumée em si vous avez 'em.

1
répondu Shog9 2008-09-14 04:12:43

je dirais imiter les diagnostics que .NET lui-même utilise (Trace et Debug).

créer une classe" output " qui peut avoir différentes classes qui adhèrent à une interface de sortie de texte. Vous reportez à la classe output, elle envoie automatiquement la sortie donnée aux classes que vous avez ajoutées (ConsoleOutput, TextFileOutput, WhateverOutput).. Et ainsi de suite.. Cela vous laisse ouverte afin d'ajouter d'autres "sortie" (tels que xml/xslt pour obtenir un bien formaté rapport?).

découvrez Collection Des Écouteurs De Trace pour voir ce que je veux dire.

1
répondu Rob Cooper 2008-09-14 10:02:47

envisagez de remanier votre application pour séparer les parties de l'interaction utilisateur de la logique commerciale. D'après mon expérience, une telle séparation est très bénéfique à la structure de votre programme.

Pour le problème que vous essayez de résoudre ici, il devient facile pour l'interaction utilisateur à changer son comportement de Console.WriteLine vers le fichier I/o

0
répondu Jay Bazuzi 2008-09-14 06:39:13

je travaille sur l'implémentation d'une fonctionnalité similaire pour capturer la sortie envoyée à la Console et la sauvegarder dans un journal tout en passant la sortie en temps réel à la Console normale pour qu'elle ne casse pas l'application (par ex. si c'est une application de console!).

si vous essayez toujours de faire cela dans votre propre code en sauvegardant la sortie de la console (par opposition à l'utilisation d'un système de journalisation pour enregistrer juste les informations auxquelles vous tenez vraiment), je pense que vous pouvez éviter la chasse d'eau après chaque écriture, comme tant que vous outrepassez aussi Flush() et assurez-vous qu'il chasse l'original stdoutWriter vous avez sauvé aussi bien que votre fileWriter. Vous voulez faire cela dans le cas où l'application essaie de purger une ligne partielle de la console pour un affichage immédiat (tel qu'une invite d'entrée, un indicateur de progrès, etc.), pour outrepasser le tampon de ligne normal.

si cette approche a des problèmes avec le fait que la sortie de votre console est trop longtemps tamponnée, vous pourriez avoir besoin de vous assurer que WriteLine() flushes stdoutWriter (mais probablement n'a pas besoin de rincer fileWriter sauf quand votre commande Flush() override est appelée). Mais je pense que l'original Console.Out (allant en fait à la console) vidangerait automatiquement son tampon sur une nouvelle ligne, donc vous ne devriez pas avoir à le forcer.

vous pourriez aussi vouloir annuler Close () to (flush et) close your fileWriter (et probablement stdoutWriter aussi bien), mais je ne suis pas sûr si c'est vraiment nécessaire ou si un Close () dans le TextWriter de base émettrait un Flush () (que vous auriez déjà override) et vous pouvez compter sur application exit pour fermer votre fichier. Vous devriez probablement tester qu'il obtient rouge à la sortie, pour être sûr. Et soyez conscient qu'une sortie anormale (crash) ne va probablement pas flush sortie tamponnée. Si c'est un problème, bouffées de chaleur fileWriter sur newline peut être souhaitable, mais c'est une autre canette délicate de vers à travailler.

0
répondu Rob Parker 2008-12-15 18:21:02