2010-12-14 210 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没有正确保存。

因此,可能有人请告诉代码?谢谢!

的第三方工具(2008 H.卡维)的参数:

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() ;'Console.WriteLine(text);'后面,你能看到整行吗? – SwDevMan81 2010-12-14 15:02:34

+0

如果另一个Console.WriteLine(文本);放在Console.Out.Flush()之后;那么可以看到文字。 – JavaNoob 2010-12-14 16:07:01

回答

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 2010-12-15 04:20:01

+0

*注意*:可能需要重定向StandardError !!! – Andrew 2016-03-03 05:52:38

2

的System.Console类有一个SetOut方法应该做你需要什么。

您应该在程序执行开始时调用Console.SetOut(yourTextWriter)

就在程序的第一行补充一点:

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

你能告诉我在哪里添加代码?谢谢! – JavaNoob 2010-12-14 14:59:04

+0

@Java,看我的编辑。 – jjnguy 2010-12-14 15:04:00

+1

重定向您自己的输出,而不是您启动的进程的输出。 – 2010-12-14 15:24:11

5

你等待子进程结束?看起来你很早就开始阅读它的输出。它可以这样做:

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

此外,您可以开始通过代表接收输出结束之前。像这样(每个文本行都需要代理):

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

即使没有完成子进程,输出应该能够完全保存为它的唯一一个5kb文件。 – JavaNoob 2010-12-14 15:00:31

+1

它无关紧要。当你过早地调用'reader.ReadToEnd()'时,将只有整个输出的一小部分。 – detunized 2010-12-14 15:04:36

+0

代表另一个答案! – JavaNoob 2010-12-15 04:20:19

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(); 
相关问题