Reputation: 91
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
:
shellStream.WriteLine('keystroke in ascii or just string')
sshClient.CreateCommand('keystroke in ascii or just string')
and then sshClient.Execute()
;StreamWriter(shellstream)
and writing to itI'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
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