How to run commands on SSH server in C#?

You could try https://github.com/sshnet/SSH.NET. With this you wouldn't need putty or a window at all. You can get the responses too. It would look sth. like this.

SshClient sshclient = new SshClient("172.0.0.1", userName, password);    
sshclient.Connect();
SshCommand sc= sshclient .CreateCommand("Your Commands here");
sc.Execute();
string answer = sc.Result;

Edit: Another approach would be to use a shellstream.

Create a ShellStream once like:

ShellStream stream = sshclient.CreateShellStream("customCommand", 80, 24, 800, 600, 1024);

Then you can use a command like this:

  public StringBuilder sendCommand(string customCMD)
    {
        StringBuilder answer;
        
        var reader = new StreamReader(stream);
        var writer = new StreamWriter(stream);
        writer.AutoFlush = true; 
        WriteStream(customCMD, writer, stream);
        answer = ReadStream(reader);
        return answer;
    }

private void WriteStream(string cmd, StreamWriter writer, ShellStream stream)
    {
        writer.WriteLine(cmd);
        while (stream.Length == 0)
        {
            Thread.Sleep(500);
        }
    }

private StringBuilder ReadStream(StreamReader reader)
    {
        StringBuilder result = new StringBuilder();

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

While the answer by @LzyPanda works, using an SSH "shell" channel (SshClient.CreateShellStream), let alone an interactive terminal, is not a good idea for automating commands execution. You get lot of side-effects from that, like command prompts, ANSI sequences, interactive behavior of some commands, etc.

For automation, use an SSH "exec" channel (SshClient.CreateCommand):

using (var command = ssh.CreateCommand("command"))
{
    Console.Write(command.Execute());
}

If you need to execute multiple commands, repeat the above code. You can create any number of "exec" channels for one SSH connection.

Though if the commands depend on each other (first command modified the environment, e.g. variables, that are used by the latter commands), you have execute them within one channel. Use a shell syntax for that, like && or ;:

using (var command = ssh.CreateCommand("command1 && command2"))
{
    Console.Write(command.Execute());
}

If you need to continuously read the commands output use:

using (var command = ssh.CreateCommand("command"))
{
    var asyncExecute = command.BeginExecute();
    command.OutputStream.CopyTo(Console.OpenStandardOutput());
    command.EndExecute(asyncExecute);
}

You can also use ExtendedOutputStream, which contains stderr. See SSH.NET real-time command output monitoring.


Unfortunately implementation of "exec" channel in SSH.NET does not allow providing an input to the command. For that use case, you will need to resort to the "shell" channel, until this limitation is solved.

Tags:

C#

.Net

Ssh

Ssh.Net