我正在尝试编写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;
}
答案 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();
}
}
}
}