2010-12-14 7 views
4

J'ai un programme qui utilise un outil de ligne de commande tiers pour générer des journaux. La 3ème partie génère toutes ses sorties vers le STDOUT, que l'utilisateur doit ensuite utiliser la commande " > test.txt" pour enregistrer le fichier.Comment enregistrer les sorties STDOUT dans un fichier texte?

Toutefois, le programme génère en quelque sorte une certaine quantité de rapport généré mais pas le rapport entier. Ce fut test en utilisant la commande

C:\Test\ftk\ripxp>ripxp.exe -r C:\test\ftk\ntuser.dat -d "C:\System Volume\_rest ore{BB12863B-2C77-46C9-BCDA-1810E52F1089}" -p runmru > C:\test\test05.txt

sur la console de ligne de commande qui fonctionne et sur le programme qui ne fonctionne que partiellement.

Les erreurs ont été réduites à l'erreur d'argument ou à la partie d'erreur d'enregistrement de fichier (streamReader). Par conséquent, l'erreur peut être due à l'enregistrement incorrect du STDOUT.

Par conséquent, quelqu'un peut-il vous conseiller sur les codes? Merci!

Les arguments en faveur de l'outil 3ème partie (2008 H. Carvey):

RipXP v.20081001 - CLI RegRipper tool 
RipXP [-r Reg hive file] [-p plugin module][-d RP dir][-lgh] 
Parse Windows Registry files, using either a single module from the plugins folder. 
Then parse all corresponding hive files from the XP Restore Points (extracted from 
image) using the same plugin. 

-r Reg hive file...Registry hive file to parse 
-g ................Guess the hive file (experimental) 
-d RP directory....Path to the Restore Point directory 
-p plugin module...use only this module 
-l ................list all plugins 
-h.................Help (print this information) 

Ex: C:\>rip -g 
C:\>rip -r d:\cases\ntuser.dat -d d:\cases\svi -p userassist 

All output goes to STDOUT; use redirection (ie, > or >>) to output to a file. 

copyright 2008 H. Carvey 

Les Codes:

static void Main(string[] args) 
    { 
     // Automatically finds folder that starts with _restore 
     DirectoryInfo directoryInfo = new DirectoryInfo(@"C:\System Volume\"); 
     DirectoryInfo restoreFolder = directoryInfo.GetDirectories().FirstOrDefault(d => d.Name.StartsWith("_restore")); 

     // Gets the folder name 
     String baka = restoreFolder.Name; 

     if (restoreFolder == null) 
      throw new DirectoryNotFoundException(); 

      Process process = new Process(); 
      process.StartInfo.FileName = @"C:\test\ftk\ripxp\ripxp.exe"; 
      process.StartInfo.Arguments = @"-r C:\test\ftk\ntuser.dat -d C:\System Volume\" + restoreFolder.Name + " -p runmru"; 
      process.StartInfo.CreateNoWindow = false; 
      process.StartInfo.UseShellExecute = false; 
      process.StartInfo.RedirectStandardOutput = true; 
      process.StartInfo.RedirectStandardInput = true; 
      process.StartInfo.RedirectStandardError = true; 
      process.Start(); 

      String text = @"-r C:\test\ftk\ntuser.dat -d C:\System Volume\" +restoreFolder.Name + " -p runmru"; 
      Console.WriteLine(baka); 
      Console.WriteLine(text); 

      // Strangely the program only outputs the first section "-r C:\test\ftk\ntuser.dat" argument results..... 
      System.IO.StreamReader reader = process.StandardOutput; 
      String sRes = reader.ReadToEnd(); 
      StreamWriter SW; 
      SW = File.CreateText(@"C:\test\test01.txt"); 
      SW.WriteLine(sRes); 
      SW.Close(); 
      Console.WriteLine("File Created Successfully"); 
      reader.Close(); 

    } 
+0

Si vous ajoutez 'Console.Out.Flush() ; 'après' Console.WriteLine (texte); ', voyez-vous la ligne entière alors? – SwDevMan81

+0

Si une autre Console.WriteLine (texte); a été placé après la Console.Out.Flush(); alors le texte peut être vu. – JavaNoob

Répondre

3

Vous pouvez .NET vous informer lorsque le processus est sorti puis lire la sortie. Parce que, comme détunized mentionné dans sa réponse + commentaire, si vous appelez reader.ReadToEnd() avant qu'il ne soit terminé, vous n'obtiendrez pas toute la sortie. Si vous y réfléchissez, c'est tout à fait évident - les données n'ont pas encore été produites, alors comment pouvez-vous attendre du lecteur qu'il le lise? En utilisant des événements, vous ne bloquerez pas la méthode qui démarre le thread, ce qui peut être très utile si vous avez une application graphique et que vous ne voulez pas geler l'interface utilisateur pendant l'exécution du processus fils.

// tell it to raise events and hook up a callback to when it completes 
process.EnableRaisingEvents = true; 
process.Exited += process_Exited; 
process.Start(); 

Cette méthode sera appelée lorsque le processus est terminé:

void process_Exited(object sender, EventArgs e) 
{ 
    var process = (Process)sender; 
    using (var f = File.CreateText(@"...")) 
    { 
     f.WriteLine(process.StandardOutput.ReadToEnd()); 
    } 
} 
+0

Merci d'avoir expliqué mate! – JavaNoob

+0

* Note *: peut être nécessaire de rediriger StandardError !!! – Andrew

2

La classe System.Console dispose d'une méthode SetOut qui devrait faire ce que vous avez besoin .

Vous devez appeler le Console.SetOut(yourTextWriter) au début de l'exécution de votre programme.

ajouter ceci à la première ligne du programme:

Console.SetOut(File.CreateText(locationToSaveLogs)); 
+0

Pourriez-vous me montrer où ajouter les codes? Merci! – JavaNoob

+0

@Java, voir mon édition. – jjnguy

+1

Cela redirige votre propre sortie, pas la sortie du processus que vous démarrez. –

5

que vous attendez le processus de l'enfant à la fin? Il semble que vous commenciez à lire sa sortie trop tôt. Cela pourrait être fait comme ceci:

process.Start(); 
process.WaitForExit(); 

De plus, vous pouvez commencer à recevoir la sortie via les délégués avant qu'elle ne se termine. Comme cela (le délégué est appelé à chaque ligne de texte):

process.OutputDataReceived += delegate(object sender, DataReceivedEventArgs e) 
{ 
    // Store e.Data somewhere. 
}; 
+0

Non, même sans le processus de l'enfant à être terminé, la sortie devrait être en mesure d'enregistrer pleinement que son seul fichier de 5 kb. – JavaNoob

+1

Peu importe sa taille. Lorsque vous appelez 'reader.ReadToEnd()' trop tôt, il n'y aura qu'une petite fraction de la sortie entière. – detunized

+0

Reprend une autre réponse! – JavaNoob

0

Vous devez utiliser l'événement OutputDataReceived.Cet article MSDN explique comment cela se fait:

https://msdn.microsoft.com/en-us/library/system.diagnostics.process.outputdatareceived(v=vs.110).aspx?cs-save-lang=1&cs-lang=csharp#code-snippet-2

A l'intérieur du gestionnaire écrire la sortie vers un fichier en utilisant le StreamWriter comme:

StreamWriter sw = new StreamWriter(sOutputFilePath); 
    Process process = new Process(); 
    process.StartInfo.FileName = "ipconfig.exe"; 
    process.StartInfo.UseShellExecute = false; 
    process.StartInfo.RedirectStandardOutput = true; 
    process.OutputDataReceived += new DataReceivedEventHandler((sender, e) => 
    { 
     if (!String.IsNullOrEmpty(e.Data)) 
     { 
      sw.WriteLine(e.Data); 
     } 
    }); 

    process.Start(); 
    process.BeginOutputReadLine(); 
    process.WaitForExit(); 
    sw.Close(); 
Questions connexes