2

3つのコントロールを持つフォームがあります。

  1. ユーザーがコンソールアプリケーションに送信するコマンドを入力するためのテキストボックス、
  2. 送信するコマンドを確認するためのボタンと
  3. アプリケーションからの出力を表示するための読み取り専用テキストボックス。

私が欲しいのは、ユーザーが最初のテキストボックスにコマンドを入力し、ボタンを押して入力し、2番目のテキストボックスを介してフィードバックを受け取ることです。

使い方は知っていますProcessStartInfo.RedirectStandardOutputが、使用するとアプリがハングしますStandardOutput.ReadToEnd()

非同期を確認しましたProcess.BeginOutputReadLine()が、アプリがハングしなくても、どういうわけかテキストボックスに応答がなく、まったく何も起こりません。

これが私のコードです:

public partial class MainForm : Form
{

    private void MainForm_Load(object sender, EventArgs e)
    {
        InitializeInterpreter();
    }

    private void InitializeInterpreter()
    {
        InterProc.StartInfo.UseShellExecute = false;
        InterProc.StartInfo.FileName = "app.exe";
        InterProc.StartInfo.RedirectStandardInput = true;
        InterProc.StartInfo.RedirectStandardOutput = true;
        InterProc.StartInfo.RedirectStandardError = true;
        InterProc.StartInfo.CreateNoWindow = true;
        InterProc.OutputDataReceived += new DataReceivedEventHandler(InterProcOutputHandler);

        InterProc.Start();
    }

    private static void InterProcOutputHandler(object sendingProcess, DataReceivedEventArgs outLine)
    {
        if (!String.IsNullOrEmpty(outLine.Data))
        {
           OutputTextBox.Append(Environment.NewLine + outLine.Data);
        }
    }

    private void Enterbutton_Click(object sender, EventArgs e)
    {
        InterProc.StandardInput.Write(CommandtextBox.Text);
        InterProc.BeginOutputReadLine();
    }
}

これをスムーズに実行する方法はありますか?ありがとう。

4

4 に答える 4

7

インタラクティブなものが必要な場合は、このコードを機能させます(変更したもの、変更の詳細は以下を参照)

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

そこで、プロセスが開始された直後にBeginOutputReadLineを移動しました。これにより、実際には1回だけ呼び出されます。また、スレッド呼び出しをクリーンアップするために必要な呼び出しを行いました。うまくいけば、これはあなたのために働くはずです。

于 2009-11-20T20:15:22.813 に答える
6

私が見つけた最善の解決策は次のとおりです。

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);
    }
}
于 2010-02-15T18:41:38.500 に答える
1

私は次のようなコードを使用しました:

    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;

    }

しかし、それはインタラクティブではありません。ただし、アプリがインタラクティブである場合は、とにかくより多くのコードが必要になります。

于 2009-11-19T19:23:44.167 に答える
0

どこに電話しStandardOutput.ReadToEnd()ますか?Process.WaitForExit()以前に電話していたので、私はかつて同様の問題を抱えていましたStandardOutput.ReadToEnd()。大量の入力があり、完了する前に出力バッファーがいっぱいになり、プロセスがブロックされました。

StandardOutput.ReadToEnd()の前に電話する必要がありますProcess.WaitForExit()

于 2009-11-19T20:01:34.387 に答える