C# StandardOutput 挂起,如何检测它正在等待输入? [英] C# StandardOutput hangs, how can I detect it's waiting for input?

查看:32
本文介绍了C# StandardOutput 挂起,如何检测它正在等待输入?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用 C# 处理进程(使用 Process 和 ProcessStartInfo)已经有一段时间了.现在,只有一个问题真正困扰我,但仍然没有找到解决方法.

当应用程序等待"某些输入时,StandardOutput 将挂起.这意味着,如果您使用 ReadToEnd,它将永远不会返回(因为实际输入窗口是不可见的).

现在,当我使用 StandardInput 提供输入时,这会产生问题.例如:

  1. 使用 C# 启动流程
  2. 使用 StandardInput 输入命令.
  3. 开始读取输出流.
  4. 根据上次输出运行另一个.

现在问题来了:我无法判断进程是在等待输入还是仍在生成输入,因为我的进程卡住"以从 StandardOutput 读取(它是在同一线程上完成的).

我需要在我的命令运行后读取输出,运行一些算法,然后根据之前的命令输出运行另一个命令.

有什么方法可以检测正在运行的进程是否已完成加载我的命令并等待新输入?就像 cmd 一样?

解决方案

试图按照 Peter 的回答,我在 StandardOutput 的末尾没有找到任何特殊的分隔符(我也检查了 ErrorOutput).

想到这里,我想,为什么不使用 echo 来模拟"一个分隔符呢?所以我放了这段代码,它允许我运行一个特定的命令并立即在同一线程上获得输出:

///<摘要>///用于写入 bash 的字符串,并允许我们检测 bash 何时完成写入输出.///</总结>const string delimiterString = "#WAITING";///<总结>///运行指定的命令并返回它的输出.///</总结>///<param name="command"></param>///<returns></returns>公共字符串运行命令(字符串命令){sessionProcess.StandardInput.WriteLine(command);//添加一个特殊的字符串在输出等待时被识别sessionProcess.StandardInput.WriteLine("echo "" + delimiterString + """);字符串输出 = "";int lastChr = 0;做{lastChr = sessionProcess.StandardOutput.Read();字符串 outputChr = null;outputChr += sessionProcess.StandardOutput.CurrentEncoding.GetString(new byte[] { (byte)lastChr });输出 += outputChr;if (output.EndsWith(delimiterString)){//删除分隔符output = output.Replace(Environment.NewLine + delimiterString, "");output = output.Replace(delimiterString + Environment.NewLine, "");//Console.Write(输出);休息;}} while (lastChr > 0);返回输出;}

I have been working with processes (using the Process and ProcessStartInfo) with C# quite some time. Now, there is only one question that really bothered me and still haven't managed to find a way to work it out.

The StandardOutput will hang when the application is "waiting" for some input. Which means, if you are using ReadToEnd it will never return (as the actual input window is invisible).

Now, this creates a problem when I'm using the StandardInput to provide the input. For example:

  1. Starting the process with C#
  2. Entering a command using StandardInput.
  3. Start reading the stream for the ouptut.
  4. Running another one based on the last output.

Now this is the problem: I can't tell whether the process is waiting for input or it's still generating one, as my process "gets" stuck to read from the StandardOutput (it's done on the same thread).

I need to read the output after my command ran, run some algorithms and then run another command based on the previous command output.

Is there is any way of detecting if the process running finished loading my command and waiting for new input? Just like the cmd does?

解决方案

Trying to follow Peter answer, I haven't found any special delimiter at the end of the StandardOutput (I checked the ErrorOutput as well).

Thinking of this through I thought, why not used echo to "simulate" a delimiter? So I put up this code which allows me to run a specific command and obtain the output immediately on the same thread:

    /// <summary>
    /// A string used to write into the bash and allows us to detect when the bash finished to write it's output.
    /// </summary>
    const string delimiterString = "#WAITING";

    /// <summary>
    /// Runs the specified command and return it's output.
    /// </summary>
    /// <param name="command"></param>
    /// <returns></returns>
    public string RunCommand(string command)
    {
        sessionProcess.StandardInput.WriteLine(command);

        // Add a special string to be recognized when output is waiting
        sessionProcess.StandardInput.WriteLine("echo "" + delimiterString + """);

        string output = "";
        int lastChr = 0;

        do
        {
            lastChr = sessionProcess.StandardOutput.Read();

            string outputChr = null;
            outputChr += sessionProcess.StandardOutput.CurrentEncoding.GetString(new byte[] { (byte)lastChr });
            output += outputChr;

            if (output.EndsWith(delimiterString))
            {
                // Remove delimeter
                output = output.Replace(Environment.NewLine + delimiterString, "");
                output = output.Replace(delimiterString + Environment.NewLine, "");

                // Console.Write(output);
                break;
            }

        } while (lastChr > 0);

        return output;
    }

这篇关于C# StandardOutput 挂起,如何检测它正在等待输入?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆