C# process.standardoutput.ReadToEnd()是否始终为空?

C# process.standardoutput.ReadToEnd()是否始终为空?,c#,process,C#,Process,我正在启动一个控制台应用程序,但是当我重定向标准输出时,我总是一无所获 当我不重定向它,并将CreateNoWindow设置为false时,我可以在控制台中正确地看到所有内容,但当我重定向它时,StandardOutput.ReadToEnd()始终返回空字符串 Process cproc = new Process(); cproc.StartInfo.CreateNoWindow = true; cproc.StartInfo.FileName

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

当我不重定向它,并将
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();
        }

退出的
EventHandler cproc\u
仅将
stop
设置为
true
。有人能解释一下为什么
结果
总是
字符串。为空吗?

您禁用了标准输出的重定向。试着改变

cproc.StartInfo.RedirectStandardOutput = false;
进入

以下示例是否适用于您

// 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();

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

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

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

编辑:正如我在评论中所建议的,您应该在不同的线程中阅读标准输出和标准错误。不要等到进程退出—这可能会导致死锁,您正在等待进程退出,但进程正在阻止尝试写入stderr/stdout,因为您没有从缓冲区读取


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

摆脱循环,将调用移动到
ReadToEnd
cproc\u Exited

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

    // 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;
    }

如果我将其更改为while(!stop){}s+=convproc.StandardOutput.ReadToEnd();我有一个死锁嘿,它起作用了!!看来我的朋友(谁做的控制台程序)把它搞砸了!它会将所有内容写入错误流!!我得和他谈谈,也许他能解决这个问题。谢谢你的快速回答!你把我从坐在电脑前一小时又一小时,试图寻找一个愚蠢的错误中解救出来:)@alex:去掉那个while循环-它不应该在那里。理想情况下,使用单独的线程-一个用于读取
StandardOutput
,另一个用于读取
StandardError
。我现在将其从
ReadToEnd
更改为
ReadLine
@alex:在这种情况下,您将需要一个循环(直到ReadLine返回false)-但除非您在进程完成之前确实需要数据,我强烈建议您从两个线程使用ReadToEnd(一个用于stdout,一个用于stderr)。这会使窗口出现,但这是空的,并且我的结果字符串也是空的。这真让人困惑。您是否检查了标准错误:
output=p.StandardError.ReadToEnd()?坏主意:如果进程试图写入大量数据,而没有任何数据读取,则进程将挂起。
    // 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;
    }