C# 如何将标准输出保存到文本文件?

C# 如何将标准输出保存到文本文件?,c#,text,stdout,C#,Text,Stdout,我有一个利用第三方命令行工具生成日志的程序。第三方生成所有输出到标准输出,用户必须使用>test.txt“命令保存文件 但是,程序会以某种方式生成一定数量的报告,但不会生成整个报告。这是使用命令进行的测试 C:\Test\ftk\ripxp>ripxp.exe-r C:\Test\ftk\ntuser.dat-d“C:\System Volume\\u rest” ore{BB12863B-2C77-46C9-BCDA-1810E52F1089}“-p runmru>C:\test\test05

我有一个利用第三方命令行工具生成日志的程序。第三方生成所有输出到标准输出,用户必须使用
>test.txt“
命令保存文件

但是,程序会以某种方式生成一定数量的报告,但不会生成整个报告。这是使用命令进行的测试

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

在命令行控制台上运行,在程序上仅部分运行

错误被缩小到参数错误或文件保存错误部分(streamReader)。因此,错误可能是由于未正确保存标准输出

因此,有人可以就代码提供建议吗?谢谢

第三方工具的论据(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();

    }

Console类有一个方法,可以完成您需要的任务

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

只需在程序的第一行添加以下内容:

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

您是否正在等待子进程完成?看起来您开始读取其输出太早了。可以这样做:

process.Start();
process.WaitForExit();
此外,您还可以在输出完成之前通过代理开始接收输出。如下所示(每行文本都会调用代理):


您可以让.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());
    }
}

您需要使用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();

不,即使没有完成子进程,输出也应该能够完全保存为一个5kb的文件。不管它有多小。如果调用
reader.ReadToEnd()
太快,则只会有整个输出的一小部分
控制台后写入行(文本),你看到整行了吗?如果另一个控制台.WriteLine(文本);放置在Console.Out.Flush()之后;然后可以看到文本。这会重定向您自己的输出,而不是您启动的进程的输出。@Hans,是的。我认为OP遇到的问题是将输出重定向到文件。这将使他在程序运行时不需要重定向输出。@jinguy:很明显,这并不能解决问题,只是对一个没有被问到的问题的一种回答。@Patrick。你说得对。不过,这仍然是很好的知识。所以我就不说了,事实上我找到了一些有趣的答案。它实际上并没有重定向标准。它重定向.net控制台类输出。这是两件不同的事情,例如,如果您从非托管代码执行printf,Console.SetOut()无效-printf仍然打印到控制台。(对我来说很不幸:))
void process_Exited(object sender, EventArgs e)
{
    var process = (Process)sender;
    using (var f = File.CreateText(@"..."))
    {
        f.WriteLine(process.StandardOutput.ReadToEnd());
    }
}
    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();