C#Stop在文本框NOT CONSOLE APP中等待用户输入

时间:2012-05-08 18:26:06

标签: c# multithreading event-listener

我正在尝试编写SSH客户端。我使用Windows窗体不是控制台应用程序。我不想使用它,因为我想学习如何工作......无论如何转向问题。我有一个while循环,只要我的shell打开就会运行。但是为了通过我的文本框将输入发送到Ssh服务器,我需要它等待输入。我添加了一个侦听ENTER KEY的事件监听器。然后获取然后输入我有一个返回数据的函数。在该函数内部是一个while循环,只要变量为true就运行。关于enter的列表的全部内容是我将更改在我的函数运行中保留的varibale,以便它退出并返回文本框内的数据。

所以我需要一种方法来覆盖函数内部的while循环并将变量设置为false。我听说过覆盖以及穿线的事情,但我不知道该怎么做。

这是我的代码!

//Variables
public string mHost;
SshShell mShell;
public string mInput;
string pattern = "";
bool mInputHolder = true;

//Initiate form!
public Form1()
{
    InitializeComponent();

    txthost.Text = "sdf.org";
    txtuser.Text = "kalle82";
    txtpass.Text = "XXXX";
    string pattern = "sdf:";
    this.txtInput.KeyPress += new System.Windows.Forms.KeyPressEventHandler(checkforenter);
}

public void button1_Click(object sender, EventArgs e)
{
    try
    {
        mShell = new SshShell(Host, User);
        mShell.Password = Pass;
        //WRITING USER MESSAGE
        txtOutput.AppendText("Connecting...");
        mShell.Connect();
        txtOutput.AppendText("OK");
        //txtOutput.AppendText("Enter a pattern to expect in response [e.g. '#', '$', C:\\\\.*>, etc...]: ");
        //Stop for user input

        mShell.ExpectPattern = pattern;
        mShell.RemoveTerminalEmulationCharacters = true;

        while (mShell.ShellOpened)
        {
            txtOutput.AppendText("\r\n" + "TERMINAL MODE ENGAGED");
            txtOutput.AppendText(mShell.Expect( pattern ));
            string data = userInput();
            if (data == "") break;
            //Data from termninal --> Append to text
            string output = mShell.Expect(Pattern);
            txtOutput.AppendText(output);
        }
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }

}

public void checkforenter(object sender, System.Windows.Forms.KeyPressEventArgs e)
{
    if (e.KeyChar == (char)13)
    {
        mInputHolder = false;
    }
}

public string userInput()
{
    while (mInputHolder == true)
    {

    }
    mInputHolder = true;
    return txtInput.Text;
}

2 个答案:

答案 0 :(得分:2)

您可能会发现创建一个扩展TextReader的类然后将Console.SetIn设置为该类很有用。在您创建的该类的构造函数中,它具有您要观察的文本框作为输入参数。从那里使用TextReader的覆盖功能来完成你需要做的事情。没有Whileloops,没有多线程,没有并发问题。这只是我的2美分。这是一篇SIMILAR文章,展示如何重定向输出。重定向输入的概念相同。

http://saezndaree.wordpress.com/2009/03/29/how-to-redirect-the-consoles-output-to-a-textbox-in-c/

答案 1 :(得分:1)

基本上你的问题是无法解决的。如果您在按钮中阻止代码,请单击以等待用户输入,您将冻结UI,这将阻止任何人提供所述输入;这被称为死锁。

您可以在按钮单击中打开shell,然后在输入后附加到它,或者您可以等到您已经有输入发送到shell之后再打开它。

既然你要了一些代码,这里是我的'hello world of a shell'的例子。我实际上是用它来玩WPF。有一个用于输入的文本框,一个用于显示输出的文本框,以及一个用于将输入文本框中的数据发送到shell的按钮。要意识到这既不是一个生产质量的例子,也不是专门针对你的问题编写的,但它应该证明了解决问题的整体方法。

    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private Process cmd;
        private bool scrollAtBottom = false;
        public MainWindow()
        {
            InitializeComponent();

            Closed+=new EventHandler(MainWindow_Closed);
            textBlock1.Text = "";

            textBox1.Focus();
        }

        private void button1_Click_1(object sender, RoutedEventArgs e)
        {
            if (cmd == null || cmd.HasExited)
            {
                cmd = new Process();
                cmd.StartInfo.CreateNoWindow = false;
                cmd.StartInfo.FileName = "cmd.exe";
                cmd.StartInfo.RedirectStandardInput = true;
                cmd.StartInfo.RedirectStandardOutput = true;
                cmd.StartInfo.UseShellExecute = false;

                cmd.OutputDataReceived += new DataReceivedEventHandler(cmd_OutputDataReceived);

                cmd.Start();
                cmd.BeginOutputReadLine();
            }

            cmd.StandardInput.WriteLine(textBox1.Text);

            textBox1.Text = "";
        }

        private void cmd_OutputDataReceived(object sender, DataReceivedEventArgs e)
        {
            textBlock1.Dispatcher.Invoke(new Action(() =>
            {
                textBlock1.Text += e.Data + Environment.NewLine;
                scrollViewer1.ScrollToEnd();
            }));
        }

        private void MainWindow_Closed(object sender, EventArgs e)
        {
            if (cmd != null && !cmd.HasExited)
            {
                //exit nicely
                cmd.StandardInput.WriteLine("exit");
                if (!cmd.HasExited)
                {
                    //exit not nicely
                    cmd.Kill();
                }
            }
        }
    }