0

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

所以我需要一种方法来覆盖函数内部的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;
}
4

2 回答 2

2

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

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

于 2012-05-08T18:33:01.797 回答
1

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

您可以通过单击按钮打开外壳,然后在输入后稍后附加到外壳,或者您可以等到已经有输入发送到外壳后再打开它。

由于您要求提供一些代码,因此这是我的“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();
                }
            }
        }
    }
于 2012-05-08T18:39:06.340 回答