2010-12-14 4 views
4

У меня есть программа, которая использует сторонний инструмент командной строки для генерации журналов. Третья сторона генерирует весь свой вывод в STDOUT, который затем должен использовать команда " > test.txt" для сохранения файла.Как сохранить выходы STDOUT в текстовый файл?

Однако программа каким-то образом генерирует определенное количество отчетов, но не весь отчет. Это был тест с помощью команды

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

на консоли командной строки, которая работает и по программе, которая работает только частично.

Ошибки были сужены до ошибки аргументов или части ошибки сохранения файла (streamReader). Поэтому ошибка может быть вызвана неправильной сохранностью STDOUT.

Поэтому может кто-нибудь проконсультироваться по кодам? Благодаря!

Аргументы для инструмента 3-й партии (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 

В коды:

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

Если добавить 'Console.Out.Flush() ; 'after' Console.WriteLine (текст);', вы видите всю строку? – SwDevMan81

+0

Если другой Console.WriteLine (текст); был помещен после Console.Out.Flush(); то текст можно увидеть. – JavaNoob

ответ

3

Вы можете иметь .NET сообщить вам, когда процесс завершился, а затем читать вывод. Потому что, как описано в его ответе + комментарии, если вы назовете reader.ReadToEnd() до его завершения, вы не получите весь вывод. Если вы думаете об этом, это совершенно очевидно - данные еще не созданы, так как вы можете ожидать, что читатель прочитает его?

С помощью событий вы не будете блокировать метод, который запускает поток, который может быть весьма полезен, если у вас есть приложение GUI и вы не хотите замораживать пользовательский интерфейс во время работы дочернего процесса.

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

Этот метод вызывается, когда процесс завершен:

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

Спасибо за объяснение помощника! – JavaNoob

+0

* Примечание *: может потребоваться перенаправить StandardError !!! – Andrew

2

Класс System.Console имеет SetOut метод, который должен делать то, что вам нужно ,

Вы должны позвонить в Console.SetOut(yourTextWriter) в начале вашей программы.

Просто добавьте это в первой строке программы:

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

Не могли бы вы показать мне, где добавить коды? Благодаря! – JavaNoob

+0

@Java, см. Мое редактирование. – jjnguy

+1

Это перенаправляет ваш собственный вывод, а не вывод того процесса, который вы запускаете. –

5

Ждет дочерний процесс до конца? Похоже, вы начинаете читать свой результат слишком рано. Это можно сделать следующим образом:

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

Кроме того, вы можете начать получать результат через делегатов до его завершения. Как это (делегат вызывается для каждой строки текста):

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

Нет, даже если дочерний процесс не будет завершен, вывод должен быть в состоянии полностью сохранить его в качестве только файла 5 КБ. – JavaNoob

+1

Неважно, насколько он мал. Когда вы вызываете 'reader.ReadToEnd()' слишком скоро, будет только небольшая часть всего вывода. – detunized

+0

Отправляется за другой ответ! – JavaNoob

0

Вы должны использовать событие OutputDataReceived.В этой статье MSDN объясняет, как это делается:

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

Внутри обработчика записи вывода в файл, используя StreamWriter как:

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(); 
Смежные вопросы