【问题标题】:redirecting output to the text file c#将输出重定向到文本文件c#
【发布时间】:2013-04-21 19:36:42
【问题描述】:

这是我的代码:

Process pr2 = new Process();
pr2.StartInfo.FileName = "show-snps";
pr2.StartInfo.Arguments = @"-Clr -x 2 out.delta > out.snps";
pr2.Start();
pr2.WaitForExit();

show-snps 写入错误。当我删除部分“> out.snps”时,一切正常,它将结果写入终端,但我需要将其重定向到文本文件。 我该怎么做?

【问题讨论】:

  • 错误用法。建议阅读手册
  • 但是当我将所有内容复制到命令行时没有错误

标签: c# redirect


【解决方案1】:

这是一个老问题,但它出现在第一个谷歌链接上,用于搜索如何将已启动进程的标准输出重定向到文件。

我认为行之有效的答案是添加一个 OutputDataReceived 事件并写入那里的文件。

这是一个完整的工作示例。

using System;
using System.IO;
using System.Diagnostics;
using System.Text;

class StandardAsyncOutputExample
{

    public static void Main()
    {
        var outputStream = new StreamWriter("output.txt");
        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))
            {
                outputStream.WriteLine(e.Data);
            }
        });

        process.Start();
       
        process.BeginOutputReadLine();

        process.WaitForExit(); 
        process.Close();
       
        outputStream.Close();

        Console.WriteLine("\n\nPress any key to exit.");
        Console.ReadLine();
    }
}

【讨论】:

    【解决方案2】:

    它不起作用,因为 > 重定向受 cmd.exe shell 支持。请尝试以下代码。

    Process pr2 = new Process();
    pr2.StartInfo.FileName = @"c:\windows\system32\cmd.exe";
    pr2.StartInfo.Arguments = @"/k \"show-snps -Clr -x 2 out.delta > out.snps\"";
    pr2.Start();
    pr2.WaitForExit();
    

    【讨论】:

    • 如果 Arguments 字符串被声明为 Verbatim(以 @ 开头),那么您不能用斜杠转义双引号。而是放入两个相邻的双引号来表示一个。上面的例子应该是:@"/k ""show-snps -Clr -x 2 out.delta > out.snps""";
    • @erict;我有同样的问题。该解决方案足以运行该过程。但我想知道cmd中抛出的错误。我尝试使用 pr2.StandardError.ReadToEnd().ToString().Split(new[] { ':' }) 和 RedirectStandardError = true;因此,执行时很长时间没有错误。但它永远不会停止返回一些东西。所以,我想知道,在执行命令后如何读取错误,使用 cmd.exe /k ""some command here > output.file""。请帮忙。
    【解决方案3】:

    当你像这样启动程序时,你不能像那样重定向。它需要像 CMD.EXE 这样的 shell 来执行此操作。

    相反,您需要将ProcessStartInfo.RedirectStandardOutput 设置为您自己管理的流。

    There's an example here.

    该示例显示了如何获取控制台进程通过 StreamReader 创建的数据。根据您的要求,您将从该 StreamReader 读取并写入 FileStream 输出。

    如果有任何帮助,这里是我多年前写的一个实用程序类(用于 .Net 2),它可能具有指导意义:

    using System;
    using System.IO;
    using System.Threading;
    using System.Diagnostics;
    using System.Collections;
    using System.Collections.Specialized;
    
    
    namespace ProcessUtilities
    {
        /// <summary>
        /// Encapsulates an executable program.
        /// This class makes it easy to run a console app and have that app's output appear
        /// in the parent console's window, and to redirect input and output from/to files.
        /// </summary>
        /// <remarks>
        /// To use this class:
        /// (1) Create an instance.
        /// (2) Set the ProgramFileName property if a filename wasn't specified in the constructor.
        /// (3) Set other properties if required.
        /// (4) Call Run().
        /// </remarks>
    
        public class Executable
        {
            #region Constructor
    
            /// <summary>Runs the specified program file name.</summary>
            /// <param name="programFileName">Name of the program file to run.</param>
    
            public Executable(string programFileName)
            {
                ProgramFileName = programFileName;
    
                _processStartInfo.ErrorDialog            = false;
                _processStartInfo.CreateNoWindow         = false;
                _processStartInfo.UseShellExecute        = false;
                _processStartInfo.RedirectStandardOutput = false;
                _processStartInfo.RedirectStandardError  = false;
                _processStartInfo.RedirectStandardInput  = false;
                _processStartInfo.WindowStyle            = ProcessWindowStyle.Hidden;
                _processStartInfo.Arguments              = "";
            }
    
                /// <summary>Constructor.</summary>
    
            public Executable(): this(string.Empty)
            {
            }
    
            #endregion  // Constructor
    
            #region Public Properties
    
            /// <summary>The filename (full pathname) of the executable.</summary>
    
            public string ProgramFileName
            {
                get
                {
                    return _processStartInfo.FileName;
                }
    
                set
                {
                    _processStartInfo.FileName = value;
                }
            }
    
            /// <summary>The command-line arguments passed to the executable when run. </summary>
    
            public string Arguments
            {
                get
                {
                    return _processStartInfo.Arguments;
                }
    
                set
                {
                    _processStartInfo.Arguments = value;
                }
            }
    
            /// <summary>The working directory set for the executable when run.</summary>
    
            public string WorkingDirectory
            {
                get
                {
                    return _processStartInfo.WorkingDirectory;
                }
    
                set
                {
                    _processStartInfo.WorkingDirectory = value;
                }
            }
    
            /// <summary>
            /// The file to be used if standard input is redirected,
            /// or null or string.Empty to not redirect standard input.
            /// </summary>
    
            public string StandardInputFileName
            {
                set
                {
                    _standardInputFileName = value;
                    _processStartInfo.RedirectStandardInput = !string.IsNullOrEmpty(value);
                }
    
                get
                {
                    return _standardInputFileName;
                }
            }
    
            /// <summary>
            /// The file to be used if standard output is redirected,
            /// or null or string.Empty to not redirect standard output.
            /// </summary>
    
            public string StandardOutputFileName
            {
                set
                {
                    _standardOutputFileName = value;
                    _processStartInfo.RedirectStandardOutput = !string.IsNullOrEmpty(value);
                }
    
                get
                {
                    return _standardOutputFileName;
                }
            }
    
            /// <summary>
            /// The file to be used if standard error is redirected,
            /// or null or string.Empty to not redirect standard error.
            /// </summary>
    
            public string StandardErrorFileName
            {
                set
                {
                    _standardErrorFileName = value;
                    _processStartInfo.RedirectStandardError = !string.IsNullOrEmpty(value);
                }
    
                get
                {
                    return _standardErrorFileName;
                }
            }
    
            #endregion  // Public Properties
    
            #region Public Methods
    
            /// <summary>Add a set of name-value pairs into the set of environment variables available to the executable.</summary>
            /// <param name="variables">The name-value pairs to add.</param>
    
            public void AddEnvironmentVariables(StringDictionary variables)
            {
                if (variables == null)
                    throw new ArgumentNullException("variables");
    
                StringDictionary environmentVariables = _processStartInfo.EnvironmentVariables;
    
                foreach (DictionaryEntry e in variables)
                    environmentVariables[(string)e.Key] = (string)e.Value;
            }
    
            /// <summary>Run the executable and wait until the it has terminated.</summary>
            /// <returns>The exit code returned from the executable.</returns>
    
            public int Run()
            {
                Thread standardInputThread  = null;
                Thread standardOutputThread = null;
                Thread standardErrorThread  = null;
    
                _standardInput  = null;
                _standardError  = null;
                _standardOutput = null;
    
                int exitCode = -1;
    
                try
                {
                    using (Process process = new Process())
                    {
                        process.StartInfo = _processStartInfo;
                        process.Start();
    
                        if (process.StartInfo.RedirectStandardInput)
                        {
                            _standardInput = process.StandardInput;
                            standardInputThread = startThread(new ThreadStart(supplyStandardInput), "StandardInput");
                        }
    
                        if (process.StartInfo.RedirectStandardError)
                        {
                            _standardError = process.StandardError;
                            standardErrorThread = startThread(new ThreadStart(writeStandardError), "StandardError");
                        }
    
                        if (process.StartInfo.RedirectStandardOutput)
                        {
                            _standardOutput = process.StandardOutput;
                            standardOutputThread = startThread(new ThreadStart(writeStandardOutput), "StandardOutput");
                        }
    
                        process.WaitForExit();
                        exitCode = process.ExitCode;
                    }
                }
    
                finally  // Ensure that the threads do not persist beyond the process being run
                {
                    if (standardInputThread != null)
                        standardInputThread.Join();
    
                    if (standardOutputThread != null)
                        standardOutputThread.Join();
    
                    if (standardErrorThread != null)
                        standardErrorThread.Join();
                }
    
                return exitCode;
            }
    
            #endregion  // Public Methods
    
            #region Private Methods
    
            /// <summary>Start a thread.</summary>
            /// <param name="startInfo">start information for this thread</param>
            /// <param name="name">name of the thread</param>
            /// <returns>thread object</returns>
    
            private static Thread startThread(ThreadStart startInfo, string name)
            {
                Thread t = new Thread(startInfo);
                t.IsBackground = true ;
                t.Name = name;
                t.Start();
                return t;
            }
    
            /// <summary>Thread which supplies standard input from the appropriate file to the running executable.</summary>
    
            private void supplyStandardInput()
            {
                // feed text from the file a line at a time into the standard input stream
    
                using (StreamReader reader = File.OpenText(_standardInputFileName))
                using (StreamWriter writer = _standardInput)
                {
                    writer.AutoFlush = true;
    
                    for (;;)
                    {
                        string textLine = reader.ReadLine();
    
                        if (textLine == null)
                            break;
    
                        writer.WriteLine(textLine);
                    }
                }
            }
    
            /// <summary>Thread which outputs standard output from the running executable to the appropriate file.</summary>
    
            private void writeStandardOutput()
            {
                using (StreamWriter writer = File.CreateText(_standardOutputFileName))
                using (StreamReader reader = _standardOutput)
                {
                    writer.AutoFlush = true;
    
                    for (;;)
                    {
                        string textLine = reader.ReadLine();
    
                        if (textLine == null)
                            break;
    
                        writer.WriteLine(textLine);
                    }
                }
    
                if (File.Exists(_standardOutputFileName))
                {
                    FileInfo info = new FileInfo(_standardOutputFileName);
    
                    // if the error info is empty or just contains eof etc.
    
                    if (info.Length < 4)
                        info.Delete();
                }
            }
    
            /// <summary>Thread which outputs standard error output from the running executable to the appropriate file.</summary>
    
            private void writeStandardError()
            {
                using (StreamWriter writer = File.CreateText(_standardErrorFileName))
                using (StreamReader reader = _standardError)
                {
                    writer.AutoFlush = true;
    
                    for (;;)
                    {
                        string textLine = reader.ReadLine();
    
                        if (textLine == null)
                            break;
    
                        writer.WriteLine(textLine);
                    }
                }
    
                if (File.Exists(_standardErrorFileName))
                {
                    FileInfo info = new FileInfo(_standardErrorFileName);
    
                    // if the error info is empty or just contains eof etc.
    
                    if (info.Length < 4)
                        info.Delete();
                }
            }
    
            #endregion  // Private Methods
    
            #region Private Fields
    
            private StreamReader _standardError  ;
            private StreamReader _standardOutput ;
            private StreamWriter _standardInput  ;
    
            private string _standardInputFileName;
            private string _standardOutputFileName;
            private string _standardErrorFileName;
    
            ProcessStartInfo _processStartInfo = new ProcessStartInfo();
    
    
            #endregion  // Private Fields
        }
    }
    

    【讨论】:

    • 嗨@Matthew Watson,我查看了你写的类,有一个疑问我需要问一下,目前 Run() 方法等待线程完成,它不会将控制权返回给调用线程(主线程)。如何实现。
    • 在 linux 上,不使用 shell(直接由内核)支持此功能。 Ex here in C : stackoverflow.com/questions/2605130/… 我不知道它在 Windows 上是如何工作的
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-18
    • 2013-11-15
    • 2018-08-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多