C# c语言中的重定向标准输出问题#

C# c语言中的重定向标准输出问题#,c#,.net,C#,.net,您能解释一下为什么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.Us

您能解释一下为什么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();
类似的代码在使用Python时不会出现问题。
在我的例子中,以编程方式读取输出流似乎不是更好的解决方案,因为我的应用程序将启动一系列进程。

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

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


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

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

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


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

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


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


关于

您无法执行重定向,因为没有直接涉及的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");

无法执行重定向,因为没有直接涉及的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");

但是我将ProcessStartInfo.UseShellExecute设置为true,以便使用shell启动进程。在这种情况下,ProcessStartInfo.UseShellExecute的含义是什么?谢谢@这大致相当于双击一个注册文件,或者在命令行中使用
start foo.doc
,它对给定的文件类型使用shell的处理程序。“UseShellExecute=false”在WindowsService环境中以域用户身份登录时,大致不允许进程与文件系统交互,但我将ProcessStartInfo.UseShellExecute设置为true,以便使用壳在这种情况下,ProcessStartInfo.UseShellExecute的含义是什么?谢谢@这大致相当于双击一个注册文件,或者在命令行中使用
start foo.doc
——它对给定的文件类型使用shell的处理程序。“UseShellExecute=false”在WindowsService环境中以域用户身份登录时,大致不允许进程与文件系统交互。理想情况下,您应该在开始读取之前设置事件处理程序。如果不这样做,您将有丢失第一位输出的风险。例如,理想情况下,您应该在开始读取之前设置事件处理程序。如果不这样做,您将有丢失第一位输出的风险。有关示例,请参见