在c#中重定向stdout的问题

时间:2021-06-01 20:56:50

Could you please explain why the shell redirection doesn't work with System.Diagnostics.Process class? I am trying to redirect the output streams to file with the following snippet:

你能解释为什么shell重定向不能与System.Diagnostics.Process类一起使用吗?我正在尝试使用以下代码段将输出流重定向到文件:

Process p = new Process();
p.StartInfo = new ProcessStartInfo();
p.StartInfo.FileName = "java.exe";
p.StartInfo.Arguments = @"> c:\Temp\test.log 2>&1";
p.StartInfo.UseShellExecute = true;
p.Start();

The similar code works without problems with Python. Reading the output streams programmatically doesn't seem a preferable solution in my case because there will be a bunch of processes launched by my application.

类似的代码可以正常使用Python。在我的情况下,以编程方式读取输出流似乎不是一个更好的解决方案,因为我的应用程序将启动一系列进程。

3 个解决方案

#1


2  

You cannot do the redirection because there is no shell directly involved. You could run a cmd.exe session, but the proper way to do it is using the RedirectStandardOutput/Error properties. There is no problem when having many processes. This is a class I use for this.

您无法进行重定向,因为没有直接涉及shell。您可以运行cmd.exe会话,但正确的方法是使用RedirectStandardOutput / Error属性。有很多进程时没有问题。这是我用来做的一个课程。

    class HandleExecutable {
        private DataReceivedEventHandler outputHandler;

        public DataReceivedEventHandler OutputHandler
        {
            set { outputHandler = value; }
        }
        private DataReceivedEventHandler errorHandler;

        public DataReceivedEventHandler ErrorHandler
        {
            set { errorHandler = value; }
        }

        public void callExecutable(string executable, string args)
        {
            string commandLine = executable;
            string args = args;
            ProcessStartInfo psi = new ProcessStartInfo(commandLine);
            psi.UseShellExecute = false;
            psi.LoadUserProfile = false;
            psi.RedirectStandardOutput = true;
            psi.RedirectStandardError = true;
            psi.WindowStyle = ProcessWindowStyle.Minimized;
            psi.CreateNoWindow = true;
            psi.Arguments = args;
            p = new Process();
            p.StartInfo = psi;
            try
            {
                p.Start();
                p.BeginOutputReadLine();
                p.BeginErrorReadLine();
                if (outputHandler != null) p.OutputDataReceived += outputHandler;
                if (errorHandler != null) p.ErrorDataReceived += errorHandler;
                p.WaitForExit();
                p.Close();
                p.Dispose();
            }
            catch (Exception ex)
            {
                log.Error(ex.Message);
            }
        }
    }

    //On another class
    void p_ErrorDataReceived(object sender, DataReceivedEventArgs e)
    {
        //HANDLE STDERR
        if (e.Data != null && !e.Data.Equals(""))
        {
             if (!e.Data.Contains("Something")) {
             }
        }
    }

    void p_OutputDataReceived(object sender, DataReceivedEventArgs e)
    {
        //HANDLE STDOUT
        if (e.Data != null && !e.Data.Equals(""))
        {
        }
    }

    HandleExecutable he = new HandleExecutable();
    he.OutputHandler = p_OutputDataReceived;
    he.ErrorHandler = p_ErrorDataReceived;
    he.callExecutable(@"C:\java.exe","-cp foo ClassName");

#2


3  

It is because there is no shell to process those arguments. When you type your command line to shell, it gets parsed, program arguments separated from the shell "special" modifiers, and only then launched. In C# this doesn't happen because there is no "cmd.exe" or "bash" process to do it.

这是因为没有shell来处理这些参数。当您将命令行键入shell时,它会被解析,程序参数与shell“特殊”修饰符分开,然后才会启动。在C#中,这不会发生,因为没有“cmd.exe”或“bash”进程来执行此操作。

To redirect input in C# you should set p.StartInfo.RedirectStandardOutput to true, then use p.StandardOutput to read data and then write it to a file.

要在C#中重定向输入,您应该将p.StartInfo.RedirectStandardOutput设置为true,然后使用p.StandardOutput读取数据,然后将其写入文件。

Alternatively, you can run a "cmd.exe" with parameters required to execute the process and redirect its output. Although not cross-platform, this should be easier to do than to write efficient data stream passing implementation yourself.

或者,您可以运行“cmd.exe”,其中包含执行该过程所需的参数并重定向其输出。虽然不是跨平台的,但这比编写高效的数据流传递实现更容易。

#3


0  

If you want to redirect the output streams you have to configure it. Set the Redirect... properties and read the streams. You can find an example here.

如果要重定向输出流,则必须对其进行配置。设置Redirect ...属性并读取流。你可以在这里找到一个例子。

Regards

问候

#1


2  

You cannot do the redirection because there is no shell directly involved. You could run a cmd.exe session, but the proper way to do it is using the RedirectStandardOutput/Error properties. There is no problem when having many processes. This is a class I use for this.

您无法进行重定向,因为没有直接涉及shell。您可以运行cmd.exe会话,但正确的方法是使用RedirectStandardOutput / Error属性。有很多进程时没有问题。这是我用来做的一个课程。

    class HandleExecutable {
        private DataReceivedEventHandler outputHandler;

        public DataReceivedEventHandler OutputHandler
        {
            set { outputHandler = value; }
        }
        private DataReceivedEventHandler errorHandler;

        public DataReceivedEventHandler ErrorHandler
        {
            set { errorHandler = value; }
        }

        public void callExecutable(string executable, string args)
        {
            string commandLine = executable;
            string args = args;
            ProcessStartInfo psi = new ProcessStartInfo(commandLine);
            psi.UseShellExecute = false;
            psi.LoadUserProfile = false;
            psi.RedirectStandardOutput = true;
            psi.RedirectStandardError = true;
            psi.WindowStyle = ProcessWindowStyle.Minimized;
            psi.CreateNoWindow = true;
            psi.Arguments = args;
            p = new Process();
            p.StartInfo = psi;
            try
            {
                p.Start();
                p.BeginOutputReadLine();
                p.BeginErrorReadLine();
                if (outputHandler != null) p.OutputDataReceived += outputHandler;
                if (errorHandler != null) p.ErrorDataReceived += errorHandler;
                p.WaitForExit();
                p.Close();
                p.Dispose();
            }
            catch (Exception ex)
            {
                log.Error(ex.Message);
            }
        }
    }

    //On another class
    void p_ErrorDataReceived(object sender, DataReceivedEventArgs e)
    {
        //HANDLE STDERR
        if (e.Data != null && !e.Data.Equals(""))
        {
             if (!e.Data.Contains("Something")) {
             }
        }
    }

    void p_OutputDataReceived(object sender, DataReceivedEventArgs e)
    {
        //HANDLE STDOUT
        if (e.Data != null && !e.Data.Equals(""))
        {
        }
    }

    HandleExecutable he = new HandleExecutable();
    he.OutputHandler = p_OutputDataReceived;
    he.ErrorHandler = p_ErrorDataReceived;
    he.callExecutable(@"C:\java.exe","-cp foo ClassName");

#2


3  

It is because there is no shell to process those arguments. When you type your command line to shell, it gets parsed, program arguments separated from the shell "special" modifiers, and only then launched. In C# this doesn't happen because there is no "cmd.exe" or "bash" process to do it.

这是因为没有shell来处理这些参数。当您将命令行键入shell时,它会被解析,程序参数与shell“特殊”修饰符分开,然后才会启动。在C#中,这不会发生,因为没有“cmd.exe”或“bash”进程来执行此操作。

To redirect input in C# you should set p.StartInfo.RedirectStandardOutput to true, then use p.StandardOutput to read data and then write it to a file.

要在C#中重定向输入,您应该将p.StartInfo.RedirectStandardOutput设置为true,然后使用p.StandardOutput读取数据,然后将其写入文件。

Alternatively, you can run a "cmd.exe" with parameters required to execute the process and redirect its output. Although not cross-platform, this should be easier to do than to write efficient data stream passing implementation yourself.

或者,您可以运行“cmd.exe”,其中包含执行该过程所需的参数并重定向其输出。虽然不是跨平台的,但这比编写高效的数据流传递实现更容易。

#3


0  

If you want to redirect the output streams you have to configure it. Set the Redirect... properties and read the streams. You can find an example here.

如果要重定向输出流,则必须对其进行配置。设置Redirect ...属性并读取流。你可以在这里找到一个例子。

Regards

问候