Выполнять длительную команду в SSH.NET и постоянно отображать результаты в TextBox

Есть ли способ выполнить команду Linux и отобразить результат в текстовом поле в приложении Windows, таком как PuTTY.

Например, я пытаюсь выполнить следующие команды

wget http://centos-webpanel.com/cwp-latest
sh cwp-latest

используя следующий код

SshClient sshclient = new SshClient(IPtxtBox.Text, UserNameTxt.Text, PasswordTxt.Text);
sshclient.Connect();
ShellStream stream = sshclient.CreateShellStream("customCommand", 80, 24, 800, 600, 1024);

resultTxt.Text = SSHCommand.SendCommand(stream, "wget http://centos-webpanel.com/cwp-latest && sh cwp-latest");
private static void WriteStream(string cmd, StreamWriter writer, ShellStream stream)
{
    writer.WriteLine(cmd);
    while (stream.Length == 0)
        Thread.Sleep(500);
}
private static string ReadStream(StreamReader reader)
{
    StringBuilder result = new StringBuilder();

    string line;
    while ((line = reader.ReadLine()) != null)
        result.AppendLine(line);

    return result.ToString();
}
private static string SendCommand(ShellStream stream, string customCMD)
{
    StringBuilder strAnswer = new StringBuilder();

    var reader = new StreamReader(stream);
    var writer = new StreamWriter(stream);
    writer.AutoFlush = true;
    WriteStream(customCMD, writer, stream);

    strAnswer.AppendLine(ReadStream(reader));

    string answer = strAnswer.ToString();
    return answer.Trim();
}

Выполнение этой команды занимает некоторое время, и в текстовом поле результата не отображается результат.


person AAHN    schedule 20.11.2017    source источник


Ответы (1)


Во-первых, не используйте канал оболочки для автоматизации выполнения команды, если у вас нет веской причины. Используйте канал exec (CreateCommand или RunCommand в SSH.NET).

Чтобы передать вывод в TextBox, просто продолжайте читать поток в фоновом потоке:

private void button1_Click(object sender, EventArgs e)
{
    new Task(() => RunCommand()).Start();
}

private void RunCommand()
{
    var host = "hostname";
    var username = "username";
    var password = "password";

    using (var client = new SshClient(host, username, password))
    {
        client.Connect();
        // If the command2 depend on an environment modified by command1,
        // execute them like this.
        // If not, use separate CreateCommand calls.
        var cmd = client.CreateCommand("command1; command2");

        var result = cmd.BeginExecute();

        using (var reader = new StreamReader(
                              cmd.OutputStream, Encoding.UTF8, true, 1024, true))
        {
            while (!result.IsCompleted || !reader.EndOfStream)
            {
                string line = reader.ReadLine();
                if (line != null)
                {
                    textBox1.Invoke(
                        (MethodInvoker)(() =>
                            textBox1.AppendText(line + Environment.NewLine)));
                }
            }
        }

        cmd.EndExecute(result);
    }
}

Немного другой подход см. в аналогичном вопросе WPF:
Мониторинг вывода команды SSH.NET в реальном времени.

Некоторые программы, такие как Python, могут буферизовать вывод при выполнении таким образом. См.:
Как непрерывно записывать выходные данные из программы Python, работающей на удаленном хосте (Raspberry Pi), выполняемой с помощью C# SSH.NET на локальная консоль?

person Martin Prikryl    schedule 20.11.2017