C# process.standardoutput.ReadToEnd() 总是空的?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2012509/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 22:39:20  来源:igfitidea点击:

process.standardoutput.ReadToEnd() always empty?

c#process

提问by alex

I'm starting a console application, but when I redirect the standard output I always get nothing!

我正在启动一个控制台应用程序,但是当我重定向标准输出时,我总是一无所获!

When I don't redirect it, and set CreateNoWindowto false, I see everything correctly in the console, but when I redirect it, StandardOutput.ReadToEnd()always returns an empty string.

当我不重定向它并设置CreateNoWindow为 时false,我会在控制台中正确地看到所有内容,但是当我重定向它时,StandardOutput.ReadToEnd()总是返回一个空字符串。

        Process cproc = new Process();
        cproc.StartInfo.CreateNoWindow = true;
        cproc.StartInfo.FileName = Dest;
        cproc.StartInfo.RedirectStandardOutput = true;
        cproc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
        cproc.StartInfo.UseShellExecute = false;
        cproc.EnableRaisingEvents = true;
        cproc.Start();
        cproc.Exited += new EventHandler(cproc_Exited);
        while(!stop)
        {
           result += cproc.StandardOutput.ReadToEnd();
        }

The EventHandler cproc_exitedjust sets stopto true. Can someone explain why resultis always string.Empty?

EventHandler cproc_exited刚套stoptrue。有人可以解释为什么result总是string.Empty吗?

采纳答案by Jon Skeet

Why are you looping? Once it's read to the end, it's not going to be able to read any more data, is it?

你为什么要循环?一旦读到最后,它就不能再读任何数据了,是吗?

Are you sure the text is actually being written to StandardOutputrather than StandardError?

您确定文本实际上是写入StandardOutput而不是StandardError

(And yes, obviously you want to set RedirectStandardOutputto true rather than false. I assumed that was just a case of you copying the wrong version of your code.)

(是的,显然你想设置RedirectStandardOutput为 true 而不是 false。我认为这只是你复制了错误版本的代码的情况。)

EDIT: As I've advised in the comments, you should read from standard output and standard error in separate threads. Do notwait until the process has exited - this can end up with a deadlock, where you're waiting for the process to exit, but the process is blocking trying to write to stderr/stdout because you haven't read from the buffer.

编辑:正如我在评论中所建议的,您应该从不同线程中的标准输出和标准错误中读取。千万不能等到进程已退出-这可以结束了一个僵局,在你等待的过程中退出,但过程是阻止试图写入到stderr /标准输出,因为你还没有从缓冲区中读取。

Alternatively you can subscribe to the OutputDataReceived and ErrorDataReceived events, to avoid using extra threads.

或者,您可以订阅 OutputDataReceived 和 ErrorDataReceived 事件,以避免使用额外的线程。

回答by Dirk Vollmar

You have redirection of standard out disabled. Try changing

您已禁用标准输出重定向。尝试改变

cproc.StartInfo.RedirectStandardOutput = false;

into

进入

cproc.StartInfo.RedirectStandardOutput = true;

Does the following sample from MSDNwork for you?

以下来自MSDN 的示例对您有用吗?

// 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 = "Write500Lines.exe";
p.Start();
// Do not wait for the child process to exit before
// reading to the end of its redirected stream.
// p.WaitForExit();
// Read the output stream first and then wait.
string output = p.StandardOutput.ReadToEnd();
p.WaitForExit();

回答by CannibalSmith

Get rid of the loop and move the call to ReadToEndto cproc_Exited.

摆脱循环并将调用移动ReadToEndcproc_Exited

回答by meta

Best way for this is to redirect the output and wait for the events:

最好的方法是重定向输出并等待事件:

    // not sure if all this flags are needed
    process.StartInfo.CreateNoWindow = true;
    process.StartInfo.ErrorDialog = false;
    process.StartInfo.UseShellExecute = false;
    process.StartInfo.RedirectStandardError = true;
    process.StartInfo.RedirectStandardInput = true;
    process.StartInfo.RedirectStandardOutput = true;
    process.EnableRaisingEvents = true;
    process.OutputDataReceived += process_OutputDataReceived;
    process.ErrorDataReceived += process_ErrorDataReceived;
    process.Exited += process_Exited;
    process.Start();

    void process_Exited(object sender, System.EventArgs e)
    {
        // do something when process terminates;
    }

    void process_OutputDataReceived(object sender, DataReceivedEventArgs e)
    {
        // a line is writen to the out stream. you can use it like:
        string s = e.Data;
    }

    void process_ErrorDataReceived(object sender, DataReceivedEventArgs e)
    {
        // a line is writen to the out stream. you can use it like:
        string s = e.Data;
    }