【问题标题】:C# Redirecting process results to a text fileC# 将处理结果重定向到文本文件
【发布时间】:2015-06-23 10:54:38
【问题描述】:

我一直在绞尽脑汁想弄清楚为什么我不能使用 >>(附加)作为我的 p.StartInfo.Argument 的一部分。当我删除“>”时,它工作得很好,但是当我尝试使用“>”或“>>”时,我得到一个“不正确的参数”错误。我已经开始编写没有 > 或 >> 的程序,只是将输出存储到一个字符串中,然后再将其写入文件。有人可以解释为什么“>”或“>>”在这种情况下不起作用吗?

// Start the child process.
 Process p = new Process();
 // Redirect the output stream of the child process.
 p.StartInfo.UseShellExecute = false;
 p.StartInfo.RedirectStandardOutput = true;
 p.StartInfo.FileName = "attrib.exe";
startInfo.Arguments = "/S *.jpg > mypics.txt";

 p.Start();

【问题讨论】:

    标签: c# append command-line-arguments


    【解决方案1】:

    输出重定向运算符>cmd.exe 的功能,而不是操作系统。因此,使用它的天真方法是这样调用cmd

    p.StartInfo.FileName = "cmd.exe";
    startInfo.Arguments = "/C \"attrib.exe /S *.jpg > mypics.txt\"";
    

    然而,重定向输出的正确方法是首先将StartInfo.RedirectStandardOutput 设置为true(您已经这样做了),然后将Process.StandardOutput 的输出通过管道传输到文件,如下所示:

    using(StreamWriter file = new StreamWriter("mypics.txt")) {
        p.StandardOutput.CopyTo(file);
    }
    

    或者,异步版本:

    using(StreamWriter file = new StreamWriter("mypics.txt")) {
        await p.StandardOutput.CopyToAsync(file);
    }
    

    【讨论】:

    • 我还没有机会尝试我们的建议,但我很想看看双引号是否能让我摆脱使用重定向运算符。
    • 与其说是双引号,不如说是对“cmd.exe”的调用。我实际上推荐后一个版本(使用StandardOutput.CopyTo),它消除了对“cmd.exe”的依赖。
    【解决方案2】:

    这是因为>>> 不是attrib.exe 解释的参数,它们是对cmd.exe 的指令。

    您可以尝试类似的方法:

    p.StartInfo.FileName = "cmd.exe";
    p.StartInfo.Arguments = "/c attrib.exe /S *.jpg > mypics.txt";
    

    另外,这是一条红鲱鱼:

    p.StartInfo.RedirectStandardOutput = true;
    

    如果您想读取 C# 代码中的输出并自己编写文件,则可以使用此选项。使用> 输出重定向器没有帮助。

    【讨论】:

    • 本来想用redirect操作符的,但是C#强行做,不想做批处理文件。
    【解决方案3】:

    SlugFiller 的解决方案很好,但在大量输出时无法可靠地工作。问题是如果进程输出太多文本,它会挂起,因为流达到最大缓冲区大小。换句话说,流需要在进程运行时被假脱机,以防止缓冲区被填满。

    但是,有一种方法可以使用任务从输出流中接收数据并实时将其输出。

    // Start the child process.
    Process p = new Process();
    // Redirect the output stream of the child process.
    p.StartInfo.UseShellExecute = false;
    p.StartInfo.RedirectStandardOutput = true;
    p.StartInfo.FileName = "attrib.exe";
    startInfo.Arguments = "/S *.jpg > mypics.txt";
    p.Start();
    
    
    Thread stdoutThread = new Thread(new ThreadStart(WriteStandardOutput));
    stdoutThread.IsBackground = true;
    stdoutThread.Name = "stdout_writer";
    stdoutThread.Start();
    
    private void WriteStandardOutput()
    {
        using (StreamWriter sw = File.CreateText(ConsoleLogFileFullPath))
        using (StreamReader sr = p.StandardOutput)
        {
            for (;;)
            {
                string line = sr.ReadLine();
                if (line == null)
                    break;
                sw.WriteLine(textLine);
            }
            sw.Flush();
        }
    }
    

    在某些时候一定要调用stdoutThread.Join() 以确保线程完成。我已经用一些生成大量输出的代码对此进行了测试,它仍然可能溢出缓冲区,或者用极长的行打破ReadLine(),但它确实适用于几千个80字符的非常快的输出每秒行数。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-04-21
      • 1970-01-01
      • 1970-01-01
      • 2021-06-03
      • 1970-01-01
      相关资源
      最近更新 更多