Domanda

Ho bisogno di consigli su come fare in modo che la mia applicazione console C# visualizzi il testo all'utente tramite l'output standard pur potendo accedervi in ​​seguito.La caratteristica effettiva che vorrei implementare è scaricare l'intero buffer di output in un file di testo alla fine dell'esecuzione del programma.

La soluzione alternativa che utilizzo anche se non trovo un approccio più pulito è la sottoclasse TextWriter sovrascrivendo i metodi di scrittura in modo che entrambi scrivano su un file e chiamino lo scrittore stdout originale.Qualcosa come questo:

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

Vedi che scrive e scarica il file continuamente.Mi piacerebbe farlo solo alla fine dell'esecuzione, ma non sono riuscito a trovare alcun modo per accedere al buffer di output.

Inoltre, scusate le inesattezze con il codice sopra (ho dovuto scriverlo ad hoc, Scusa ;).

È stato utile?

Soluzione

La soluzione perfetta per questo è usare log4net con un appender di console e un appender di file.Sono disponibili anche molti altri appender.Consente inoltre di attivare e disattivare i diversi appender in fase di runtime.

Altri suggerimenti

Non penso che ci sia qualcosa di sbagliato nel tuo approccio.

Se desideri un codice riutilizzabile, considera l'implementazione di una classe chiamata MultiWriter o qualcosa del genere che prende come input due (o N?) TextWriter trasmette e distribuisce tutti i mandati, le vampate, ecc.a quei flussi.Quindi puoi fare questa cosa su file/console, ma altrettanto facilmente puoi dividere qualsiasi flusso di output.Utile!

Probabilmente non è quello che vuoi, ma per ogni evenienza...Apparentemente, Implementa PowerShell una versione del venerabile tee comando.Che è praticamente destinato esattamente a questo scopo.COSÌ...fumateli se li avete.

Direi di imitare la diagnostica utilizzata da .NET stesso (Traccia e Debug).

Crea una classe di "output" che può avere classi diverse che aderiscono a un'interfaccia di output di testo.Riferisci alla classe di output, invia automaticamente l'output fornito alle classi che hai aggiunto (ConsoleOutput, TextFileOutput, AnywayOutput).E così via..Ciò ti lascia anche la possibilità di aggiungere altri tipi di "output" (come xml/xslt per ottenere un report ben formattato?).

Dai un'occhiata a Raccolta di ascoltatori di tracce per vedere cosa intendo.

Prendi in considerazione il refactoring della tua applicazione per separare le parti di interazione dell'utente dalla logica aziendale.Nella mia esperienza, una tale separazione è molto vantaggiosa per la struttura del tuo programma.

Per il problema particolare che stai cercando di risolvere qui, diventa semplice per la parte di interazione dell'utente modificare il proprio comportamento Console.WriteLine per archiviare I/O.

Sto lavorando per implementare una funzionalità simile per acquisire l'output inviato alla Console e salvarlo in un registro passando comunque l'output in tempo reale alla normale Console in modo da non interrompere l'applicazione (ad es.se è un'applicazione console!).

Se stai ancora provando a farlo nel tuo codice salvando l'output della console (invece di utilizzare un sistema di registrazione per salvare solo le informazioni che ti interessano veramente), penso che puoi evitare lo svuotamento dopo ogni scrittura, a patto che poiché esegui anche l'override di Flush() e assicurati che scarichi l'originale stdoutWriter hai salvato così come il tuo fileWriter.Vuoi farlo nel caso in cui l'applicazione stia tentando di scaricare una linea parziale sulla console per una visualizzazione immediata (come un prompt di input, un indicatore di avanzamento, ecc.), per sovrascrivere il normale buffer di linea.

Se questo approccio presenta problemi con l'output della console che viene bufferizzato troppo a lungo, potrebbe essere necessario assicurarsi che WriteLine() si scarichi stdoutWriter (ma probabilmente non ha bisogno di scaricare fileWriter tranne quando viene chiamato l'override di Flush()).Ma penserei che l'originale Console.Out (in realtà andando alla console) scaricherà automaticamente il suo buffer su una nuova riga, quindi non dovresti forzarlo.

Potresti anche voler sovrascrivere Close() per (scaricare e) chiudere il tuo fileWriter (e probabilmente stdoutWriter ), ma non sono sicuro che sia realmente necessario o se un Close() nel TextWriter di base emetterebbe un Flush() (che avresti già sovrascritto) e potresti fare affidamento sull'uscita dell'applicazione per chiudere il tuo file.Probabilmente dovresti testare che venga scaricato all'uscita, per essere sicuro.E tieni presente che un'uscita anomala (arresto anomalo) probabilmente non svuoterà l'output bufferizzato.Se questo è un problema, arrossamento fileWriter on newline può essere desiderabile, ma questa è un'altra lattina difficile da risolvere.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top