Pumar
Pumar

Reputation: 91

Sending input during command output with SSH.NET

With PuTTY, I connect to an SSH server and then I execute a command that constantly output logs (multiple lines per second). During this process I can send some keystrokes which are commands, ie. putting 123 or Esc which stops the process. If I put a valid keystroke I can see it on output device, so I always know if keystroke was sent or not.

I want to do it programmatically - connect to the SSH server, execute the main command and then send it some key strokes as commands while in the same time monitoring the logs where I can see the response to my commands.

So I want to do it with SSH.NET - it's a neat SSH tool, it outputs reliably and it's nice to work with. However I have a problem - I can connect to this server, execute a command, but while it dumps the log I cannot send it any key stroke.

Ways I've tried using CreateShellStream:

I've tried ascii codes, UTF-16 codes, strings, nothing works unfortunately.

The same thing done with Plink (PuTTY command-line tool) works just fine, but it's much messier and I would prefer to use SSH.NET. Do you know what is the difference between sending keystrokes with SSH.NET and Plink? Why does it work flawlessly with Plink? I've tried debugging it with Wireshark, unfortunately SSH makes it really difficult to do so.

With Plink I'm using basically something like this:

ProcessStartInfo psi = new ProcessStartInfo("plink.exe", arguments);
psi.RedirectStandardError = true;
psi.RedirectStandardOutput = true;
psi.RedirectStandardInput = true;
psi.UseShellExecute = false;
plink = Process.Start(psi);
StreamWriter input = plink.StandardInput;
StreamReader output = plink.StandardOutput;

input.WriteLine("startCommand"); //Starts the process responsible for logs

input.Write("950"); //It correctly sends the keystrokes

// Some code regarding reading logs from output, some other commands sent to ssh server...

Console.WriteLine("Exiting...");
input.Write('\u001b');  //ESC in UTF16

I think that SSH.NET waits for the last command to end before sending anything else but I don't know how to change it.


My tries using SSH.NET:

using (var client = new SshClient(host, user, new PrivateKeyFile(key)))
{
    int timoutCounter = 0;
    do
    {
        timoutCounter++;
        try { client.Connect(); }
        catch (Exception e)
        {
            Console.WriteLine("Connection error: " + e.Message);
        }
    } while (!client.IsConnected);

    ShellStream stream = client.CreateShellStream("shell", 200, 24, 1920, 1080, 4096);

    // it starts the process on remote ssh server that 
    stream.WriteLine("startCommand"); 
    Console.Write("Waiting for any key...");
    Console.ReadKey();

    for (int i = 0; i < 30; i++)
    {
        // Just some quick way for me to know that the device fully loaded
        stream.Expect("LogKeyWord");
    }
    Console.WriteLine("Device started");
    Console.ReadKey();

    // Different ways of entering commands during log output that I've tried

    stream.Write("5"); 
    Console.Write("Waiting for any key...");
    Console.ReadKey();

    stream.WriteLine("6");
    Console.Write("Waiting for any key...");
    Console.ReadKey();

    stream.Write("\u001b"); 
    Console.Write("Waiting for any key...");
    Console.ReadKey();

    var test97 = new StreamWriter(stream);
    test97.Write("7");
    Console.Write("Waiting for any key...");
    Console.ReadKey();

    test97.WriteLine("8");
    Console.Write("Waiting for any key...");
    Console.ReadKey();

    client.RunCommand("11");
    Console.Write("Waiting for any key...");
    Console.ReadKey();

    var test = client.CreateCommand("31");
    test.Execute();
    Console.Write("Waiting for any key...");
    Console.ReadKey();

    client.Disconnect();
}

Upvotes: 3

Views: 3084

Answers (1)

scott
scott

Reputation: 1277

Just a guess, but I would try flushing the stream.

Update:

Wrote a little experiment and I can't reproduce the problem. Take a look here: https://github.com/scottstephens-repros/SSHNetInterleavedIORepro

So this is probably an issue specific to your code, the program you're trying to run remotely, or the remote machine's OS, sshd, or configuration. My remote test machine was CentOS 7.8, with OpenSSH 7.4p1.

Upvotes: 1

Related Questions