Sending input/getting output from a console application (C#/WinForms)

前端 未结 4 458
你的背包
你的背包 2020-12-06 03:48

I have a form with 3 controls:

  1. A textbox for the user to enter commands to send to a console application,
  2. A button to confirm the commands to be sent
相关标签:
4条回答
  • 2020-12-06 04:25

    The best solution I have found is:

    private void Redirect(StreamReader input, TextBox output)
    {
        new Thread(a =>
        {
            var buffer = new char[1];
            while (input.Read(buffer, 0, 1) > 0)
            {
                output.Dispatcher.Invoke(new Action(delegate
                {
                    output.Text += new string(buffer);
                }));
            };
        }).Start();
    }
    
    private void Window_Loaded(object sender, RoutedEventArgs e)
    {
        process = new Process
        {
            StartInfo = new ProcessStartInfo
            {
                CreateNoWindow = true,
                FileName = "app.exe",
                RedirectStandardError = true,
                RedirectStandardOutput = true,
                UseShellExecute = false,
            }
        };
        if (process.Start())
        {
            Redirect(process.StandardError, textBox1);
            Redirect(process.StandardOutput, textBox1);
        }
    }
    
    0 讨论(0)
  • 2020-12-06 04:28

    I've used code something like this:

        public static void Run(string fileName, string arguments, out string standardOutput, out string standardError, out int exitCode)
        {
            Process fileProcess = new Process();
            fileProcess.StartInfo = new ProcessStartInfo
            {
                FileName = fileName,
                Arguments = arguments,
                RedirectStandardError = true,
                RedirectStandardOutput = true,
                UseShellExecute = false,
                WindowStyle = ProcessWindowStyle.Hidden,
                CreateNoWindow = true,
            };
    
            bool started = fileProcess.Start();
    
            if (started)
            {
                fileProcess.WaitForExit();
            }
            else
            {
                throw new Exception("Couldn't start");
            }
    
            standardOutput = fileProcess.StandardOutput.ReadToEnd();
            standardError = fileProcess.StandardError.ReadToEnd();
            exitCode = fileProcess.ExitCode;
    
        }
    

    But it's not interactive. But if the app is interactive, it'll take a lot more code anyway.

    0 讨论(0)
  • 2020-12-06 04:34

    If you want something interactive, I got this code to work (yours modified, details on modifications below)

        private void InitializeInterpreter()
        {
            InterProc.StartInfo.UseShellExecute = false;
            InterProc.StartInfo.FileName = "Echoer.exe";
            InterProc.StartInfo.RedirectStandardInput = true;
            InterProc.StartInfo.RedirectStandardOutput = true;
            InterProc.StartInfo.RedirectStandardError = true;
            InterProc.StartInfo.CreateNoWindow = true;
            InterProc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
            InterProc.OutputDataReceived += new DataReceivedEventHandler(InterProcOutputHandler);
    
            bool started = InterProc.Start();
    
            InterProc.BeginOutputReadLine();
    
        }
    
        private void AppendTextInBox(TextBox box, string text)
        {
            if (this.InvokeRequired)
            {
                this.Invoke((Action<TextBox, string>)AppendTextInBox, OutputTextBox, text);
            }
            else
            {
                box.Text += text;
            }
        }
    
        private void InterProcOutputHandler(object sendingProcess, DataReceivedEventArgs outLine)
        {
            AppendTextInBox(OutputTextBox, outLine.Data + Environment.NewLine);
        }
    
        private void Enterbutton_Click(object sender, EventArgs e)
        {
            InterProc.StandardInput.WriteLine(CommandTextBox.Text);
        }
    

    So, I moved the BeginOutputReadLine to just after the process is started. That ensures it's really only called once. I also did an invoke required to clean up thread calls. Hopefully this should work for you.

    0 讨论(0)
  • 2020-12-06 04:37

    Where are you calling StandardOutput.ReadToEnd()? I once had a similar problem because I was calling Process.WaitForExit() before StandardOutput.ReadToEnd(). I had a large amount of input, and the output buffer was full before completion and my process was blocked.

    You must call StandardOutput.ReadToEnd()before Process.WaitForExit().

    0 讨论(0)
提交回复
热议问题