我有一个程序,它利用第三方命令行工具生成日志。第三方生成其所有输出到STDOUT,然后用户必须使用" > test.txt"
命令保存文件。
然而,程序会以某种方式生成一定数量的报告,但不会生成整个报告。这是通过使用命令
进行测试 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 :(得分:5)
您是否在等待子进程完成?看起来你太早开始阅读它的输出。可以这样做:
process.Start();
process.WaitForExit();
此外,您可以在完成之前通过委托开始接收输出。像这样(为每行文本调用委托):
process.OutputDataReceived += delegate(object sender, DataReceivedEventArgs e)
{
// Store e.Data somewhere.
};
答案 1 :(得分: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());
}
}
答案 2 :(得分:2)
System.Console类有一个SetOut
方法,可以满足你的需要。
您应该在程序执行开始时调用Console.SetOut(yourTextWriter)
。
只需在程序的第一行添加:
Console.SetOut(File.CreateText(locationToSaveLogs));
答案 3 :(得分:0)
您需要使用OutputDataReceived事件。这篇MSDN文章解释了如何做到这一点:
处理程序内部使用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();