2010-12-14 14 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. 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.WriteLine(text); 'の後に、行全体が表示されますか? – SwDevMan81

+0

別のConsole.WriteLine(text); Console.Out.Flush()の後に配置されました。テキストが表示されます。 – JavaNoob

答えて

3

あなたは、プロセスが終了したとき、.NETがあなたに通知があり、その後、出力を読み取ることができます。彼の答え+コメントに言及されたdetunizedのように、完了する前に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

* Note *: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

子プロセスが終了していなくても、出力は唯一の5kbファイルとして完全に保存できるはずです。 – 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を使用してファイルに出力を書き込む:あなたは `Console.Out.Flushを追加する場合

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(); 
関連する問題