Xceed .NET Libraries Documentation
Welcome to Xceed Data Manipulation Compoents for .NET and .NET Standard / Basic Concepts / SFTP Capabilities / Remote Command Execution

In This Topic
    Remote Command Execution
    In This Topic

    Description

    The SSH protocol allows for the remote execution of commands on the server. This is done using a SSH logical channel. Many SSH features like SFtp and remote command execution are implemented over such channels. Every channel is multiplexed into a single encrypted SSH connection.

    As such, a remote command execution can be issued while a SFtp session is performing work since a new channel will be created to issue the command.

    Remote command execution works by the client sending a message that requests the server start the execution of a given command string. The 'command' string may contain a path and arguments. It is also possible to pass environment variables to the server before the command is executed.

    It should be noted that servers will take normal precautions to prevent the execution of unauthorized commands. At the very least, this means that the right to execute a command, and which commands are allowed will depend on the user that is authenticated on the SSH connection. These rights are determined by the server's administrator and cannot be computed on the client side.

    If a user doesn't have the rights to execute a command, an exception will be thrown but the SSH connection will not be closed. Other channels (like SFtp sessions) will continue to proceed without issue.

    Usage

    A remote command is executed using the Xceed.SSH.Client.ExecuteCommandSession Class. Its constructor needs to be supplied a SSHClient object that is connected and authenticated. Then, the Connect() method can be called, specifying the command to execute and, optionally, environment variables to set on the server before the command is executed.

    The ExecuteCommandSession class is ony available with the Xceed SFtp for .NET that is compiled for .NET 4.0 and later. The class is available with Xceed SFtp for Xamarin, all versions.

    The Connect() method returns immediately if the server accepts the command. If not, a SSHChannelRequestFailedException is thrown. The command is run on the server while control continues normall on the client side. The server might send standard output and/or standard error text output to the client. It is possible to catch that data with a Stream object using the GetOutputStream() and GetErrorStream() methods. It is also possible to send text to the command's standard input using a stream with the GetInputStream() method. With all these streams, it is often useful to wrap them around a System.Text.StreamReader or System.Text.StreamWriter object to read and write text lines. See the examples below for details.

    The ExecuteCommandSession class contains a CommandCompleted Event event that will be triggered when the command has completed on the server. At that point, the channel will have been closed but the possible exit status or exit signal (not all servers supply these values) will still be available to be read.

    Another way to watch for the completion of the command is to wait on the SessionCompletedWaitHandle.

    The ExecuteCommandSession class implements the IDisposable interface. It is good practice to dispose of an instance of the class once it is no longer needed.

    Examples

     Execute and wait for result

    The simplest way to use the ExecuteCommandSession class is to start the command and wait for the command to complete.

    using System.IO;
    
    using Xceed.SSH.Client;
    using Xceed.SSH.Core;
    using Xceed.SSH.Protocols;
    using Xceed.FileSystem;
    
    namespace DocumentationExamples.SSH
    {
      public class ExecuteCommandSession3
      {
        public void Example()
        {
          string host = "localhost";
          string username = "normal1";
          string password = "normal1";
    
          SSHClient ssh = new SSHClient();
    
          // Connect to the host
          ssh.Connect( host );
    
          try
          {
            // Log in
            ssh.Authenticate( username, password );
    
            // The remote command to execute
            string command = "dir";
    
            // Create a session that will execute a remote command
            using( ExecuteCommandSession executeCommandSession = new ExecuteCommandSession( ssh ) )
            {
              // Execute the command on the remote server, waiting until it completes
              Nullable<int> exitStatus = executeCommandSession.ExecuteCommand( command );
    
              /* Some servers will return exit information like the return code and the 'signal'
                 if the command fails. */
    
              Console.WriteLine( "Command exited with status {0}", exitStatus.HasValue ? exitStatus.ToString() : "(null)" );
    
              SSHChannelExitSignal exitSignal = executeCommandSession.ExitSignal;
              if( exitSignal != null )
              {
                Console.WriteLine( "Command exited with signal {0}: {1}", exitSignal.SignalName, exitSignal.ErrorMessage );
              }
            }
          }
          catch( SSHChannelRequestFailedException )
          {
            /* This exception is thrown by ExecuteCommandSession.Connect(). The most common
             * cause is the authenticated user does not have the rights to execute commands
             * on the server. */
          }
          finally
          {
            // Always make sure to disconnect from the server when the connection is no longer needed
            ssh.Disconnect();
          }
        }
      }
    }
    Imports System.IO
    
    Imports Xceed.SSH.Client
    Imports Xceed.SSH.Core
    Imports Xceed.SSH.Protocols
    Imports Xceed.FileSystem
    
    Namespace DocumentationExamples.SSH
      Public Class ExecuteCommandSession3
        Public Sub Example()
          Dim host As String = "localhost"
          Dim username As String = "normal1"
          Dim password As String = "normal1"
    
          Dim ssh As New SSHClient()
    
          ' Connect to the host
          ssh.Connect(host)
    
          Try
            ' Log in
            ssh.Authenticate(username, password)
    
            ' The remote command to execute
            Dim command As String = "dir"
    
            ' Create a session that will execute a remote command
            Using executeCommandSession As New ExecuteCommandSession(ssh)
              ' Execute the command on the remote server, waiting until it completes
              Dim exitStatus As Nullable(Of Integer) = executeCommandSession.ExecuteCommand(command)
    
    '           Some servers will return exit information like the return code and the 'signal'
    '             if the command fails. 
    
              Console.WriteLine("Command exited with status {0}",If(exitStatus.HasValue, exitStatus.ToString(), "(null)"))
    
              Dim exitSignal As SSHChannelExitSignal = executeCommandSession.ExitSignal
              If exitSignal IsNot Nothing Then
                Console.WriteLine("Command exited with signal {0}: {1}", exitSignal.SignalName, exitSignal.ErrorMessage)
              End If
            End Using
          Catch e1 As SSHChannelRequestFailedException
    '         This exception is thrown by ExecuteCommandSession.Connect(). The most common
    '         * cause is the authenticated user does not have the rights to execute commands
    '         * on the server. 
          Finally
            ' Always make sure to disconnect from the server when the connection is no longer needed
            ssh.Disconnect()
          End Try
        End Sub
      End Class
    End Namespace
     Fire-and-forget

    The ExecuteCommandSession class can also be used in a fire-and-forget manner.

    using System.IO;
    using System.Threading.Tasks;
    
    using Xceed.SSH.Client;
    using Xceed.SSH.Core;
    using Xceed.SSH.Protocols;
    using Xceed.FileSystem;
    
    namespace DocumentationExamples.SSH
    {
      public class ExecuteCommandSession4
      {
        public void Example()
        {
          string host = "localhost";
          string username = "normal1";
          string password = "normal1";
    
          // The remote command to execute
          string command = "dir";
    
          SSHClient ssh = new SSHClient();
    
          // Connect to the host
          ssh.Connect( host );
    
          try
          {
            // Log in
            ssh.Authenticate( username, password );
    
            Task<Nullable<int>> task = this.ExecuteRemoteCommandAsync( ssh, command );
    
            /* TODO: Perform other business that does not require the result of the remote command */
    
            /* Now that we need the result from the remote command, we will wait for it */
            Nullable<int> exitStatus = task.Result;
            Console.WriteLine( "Command exited with status {0}", exitStatus.HasValue ? exitStatus.ToString() : "(null)" );
          }
          finally
          {
            // Always make sure to disconnect from the server when the connection is no longer needed
            ssh.Disconnect();
          }
        }
    
        private async Task<Nullable<int>> ExecuteRemoteCommandAsync( SSHClient ssh, string command )
        {
          Task<Nullable<int>> executeCommandTask;
          Nullable<int> exitStatus;
    
          ExecuteCommandSession executeCommandSession = null;
    
          // Create a session that will execute a remote command
          executeCommandSession = new ExecuteCommandSession( ssh );
    
          try
          {
            // Start executing the specified command on the remote server
            executeCommandTask = executeCommandSession.ExecuteCommandAsync( command );
          }
          catch( SSHChannelRequestFailedException )
          {
            /* This exception is thrown by ExecuteCommandSession.Connect(). The most common
              * cause is the authenticated user does not have the rights to execute commands
              * on the server. */
    
            /* The 'CommandCompleted' event is not triggered when the request to launch the command fails */
    
            // Dispose of the session to free resources
            executeCommandSession.Dispose();
    
            // Rethrow the exception
            throw;
          }
    
          // Wait for the remote command to complete while allowing the calling method to continue execution
          exitStatus = await executeCommandTask;
    
          /* This code will be executed in a background thread from ThreadPool */
    
          // Dispose of the session to free resources
          executeCommandSession.Dispose();
    
          return exitStatus;
        }
      }
    }
    Imports System.IO
    Imports System.Threading.Tasks
    
    Imports Xceed.SSH.Client
    Imports Xceed.SSH.Core
    Imports Xceed.SSH.Protocols
    Imports Xceed.FileSystem
    
    Namespace DocumentationExamples.SSH
      Public Class ExecuteCommandSession4
        Public Sub Example()
          Dim host As String = "localhost"
          Dim username As String = "normal1"
          Dim password As String = "normal1"
    
          ' The remote command to execute
          Dim command As String = "dir"
    
          Dim ssh As New SSHClient()
    
          ' Connect to the host
          ssh.Connect(host)
    
          Try
            ' Log in
            ssh.Authenticate(username, password)
    
            Dim task As Task(Of Nullable(Of Integer)) = Me.ExecuteRemoteCommandAsync(ssh, command)
    
            ' TODO: Perform other business that does not require the result of the remote command 
    
            ' Now that we need the result from the remote command, we will wait for it 
            Dim exitStatus As Nullable(Of Integer) = task.Result
            Console.WriteLine("Command exited with status {0}",If(exitStatus.HasValue, exitStatus.ToString(), "(null)"))
          Finally
            ' Always make sure to disconnect from the server when the connection is no longer needed
            ssh.Disconnect()
          End Try
        End Sub
    
        Private async Function ExecuteRemoteCommandAsync(ByVal ssh As SSHClient, ByVal command As String) As Task(Of Nullable(Of Integer))
          Dim executeCommandTask As Task(Of Nullable(Of Integer))
          Dim exitStatus As Nullable(Of Integer)
    
          Dim executeCommandSession As ExecuteCommandSession = Nothing
    
          ' Create a session that will execute a remote command
          executeCommandSession = New ExecuteCommandSession(ssh)
    
          Try
            ' Start executing the specified command on the remote server
            executeCommandTask = executeCommandSession.ExecuteCommandAsync(command)
          Catch e1 As SSHChannelRequestFailedException
    '         This exception is thrown by ExecuteCommandSession.Connect(). The most common
    '          * cause is the authenticated user does not have the rights to execute commands
    '          * on the server. 
    
            ' The 'CommandCompleted' event is not triggered when the request to launch the command fails 
    
            ' Dispose of the session to free resources
            executeCommandSession.Dispose()
    
            ' Rethrow the exception
            Throw
          End Try
    
          ' Wait for the remote command to complete while allowing the calling method to continue execution
          exitStatus = await executeCommandTask
    
          ' This code will be executed in a background thread from ThreadPool 
    
          ' Dispose of the session to free resources
          executeCommandSession.Dispose()
    
          Return exitStatus
        End Function
      End Class
    End Namespace
     Capture command output

    The output of the command can be captured. Here a technique using asynchronous reading is used in order to read output and error text at the same time.

    Also shown in this example is how to pass environment variables to the server.

    using System.Collections.Generic;
    using System.IO;
    using System.Threading;
    using System.Threading.Tasks;
    
    using Xceed.SSH.Client;
    using Xceed.SSH.Core;
    using Xceed.SSH.Protocols;
    using Xceed.FileSystem;
    
    namespace DocumentationExamples.SSH
    {
      public class ExecuteCommandSession1
      {
        public void Example()
        {
          string host = "localhost";
          string username = "normal1";
          string password = "normal1";
    
          SSHClient ssh = new SSHClient();
    
          // Connect to the host
          ssh.Connect( host );
    
          try
          {
            // Log in
            ssh.Authenticate( username, password );
    
            // The remote command to execute
            string command = "dir *.*";
    
            // Some environment variables
            KeyValuePair<string, string> environmentVariable = new KeyValuePair<string, string>( "MYVARIABLE", "MYVALUE" );
    
            // Create a session that will execute a remote command
            using( ExecuteCommandSession executeCommandSession = new ExecuteCommandSession( ssh ) )
            {
              Stream commandOutputStream = null;
              Stream commandErrorStream = null;
    
              try
              {
                /* We obtain the output and error streams BEFORE starting the command so that we don't
                   miss any output. */
    
                /* If the CommandOutputStream or the CommandErrorStream object is not taken,
                   the component silently discards the incoming data. This might be desirable if
                   the output and/or error text is not needed. */
    
                // Get the command's output stream (standard output)
                commandOutputStream = executeCommandSession.GetOutputStream();
    
                // Get the command's error stream (standard error)
                commandErrorStream = executeCommandSession.GetErrorStream();
    
                /* Now that we are setup the way we want, we can safely start the remote command */
    
                // Start executing the specified command on the remote server passing the supplied environment variables to the server
                executeCommandSession.Connect( command, environmentVariable );
    
                /* Notice how we wrap the streams with StreamReader objects only after starting the command.
                   This guards against the possibility of the StreamReader object calling Stream.Read() before
                   we've started the command. */
    
                // Wrap a stream reader around the output stream
                System.IO.StreamReader outputReader = new System.IO.StreamReader( commandOutputStream );
    
                // Wrap a stream reader around the error stream
                System.IO.StreamReader errorReader = new System.IO.StreamReader( commandErrorStream );
    
                // Read a line from the output and error at the same time
                Task<string> readOutputLineTask = outputReader.ReadLineAsync();
                Task<string> readErrorLineTask = errorReader.ReadLineAsync();
    
                string line;
    
                // While either the output or error streams haven't reached end-of-file
                while( readOutputLineTask != null || readErrorLineTask != null )
                {
                  // If reading an output line has completed
                  if( readOutputLineTask != null && readOutputLineTask.IsCompleted )
                  {
                    // Get the line
                    line = readOutputLineTask.Result;
    
                    // If we have a line
                    if( line != null )
                    {
                      // Output it to the console
                      Console.WriteLine( line );
    
                      // Read another line
                      readOutputLineTask = outputReader.ReadLineAsync();
                    }
                    else
                    {
                      /* We've reached end-of-file. We don't want to read again */
                      readOutputLineTask = null;
                    }
                  }
    
                  // If reading an error line has completed
                  if( readErrorLineTask != null && readErrorLineTask.IsCompleted )
                  {
                    // Get the line
                    line = readErrorLineTask.Result;
    
                    // If we have a line
                    if( line != null )
                    {
                      // Output it to the console
                      Console.WriteLine( line );
    
                      // Read another line
                      readErrorLineTask = errorReader.ReadLineAsync();
                    }
                    else
                    {
                      /* We've reached end-of-file. We don't want to read again */
                      readErrorLineTask = null;
                    }
                  }
                }
    
                /* Because we've processed the output stream until end-of-file, we are sure that
                  the command has completed. No need to wait. 
    
                   However, if accessing the exit status or possible exit signal of the command
                   is important to the application, it is best to wait until the command has signaled it
                   has completed. At that point, the exit information will have been received. */
    
                // Wait until the command has completed
                executeCommandSession.SessionCompletedWaitHandle.WaitOne();
    
                /* Some servers will return exit information like the return code and the 'signal'
                  if the command fails. */
    
                Nullable<int> exitStatus = executeCommandSession.ExitStatus;
                Console.WriteLine( "Command exited with status {0}", exitStatus.HasValue ? exitStatus.ToString() : "(null)" );
    
                SSHChannelExitSignal exitSignal = executeCommandSession.ExitSignal;
                if( exitSignal != null )
                {
                  Console.WriteLine( "Command exited with signal {0}: {1}", exitSignal.SignalName, exitSignal.ErrorMessage );
                }
              }
              catch( SSHChannelRequestFailedException )
              {
                /* This exception is thrown by ExecuteCommandSession.Connect(). The most common
                 * cause is the authenticated user does not have the rights to execute commands
                 * on the server. */
              }
              finally
              {
                if( commandOutputStream != null )
                {
                  commandOutputStream.Close();
                  commandOutputStream = null;
                }
    
                if( commandErrorStream != null )
                {
                  commandErrorStream.Close();
                  commandErrorStream = null;
                }
              }
            }
    
          }
          finally
          {
            // Always make sure to disconnect from the server when the connection is no longer needed
            ssh.Disconnect();
          }
        }
      }
    }
    Imports System.Collections.Generic
    Imports System.IO
    Imports System.Threading
    Imports System.Threading.Tasks
    
    Imports Xceed.SSH.Client
    Imports Xceed.SSH.Core
    Imports Xceed.SSH.Protocols
    Imports Xceed.FileSystem
    
    Namespace DocumentationExamples.SSH
      Public Class ExecuteCommandSession1
        Public Sub Example()
          Dim host As String = "localhost"
          Dim username As String = "normal1"
          Dim password As String = "normal1"
    
          Dim ssh As New SSHClient()
    
          ' Connect to the host
          ssh.Connect(host)
    
          Try
            ' Log in
            ssh.Authenticate(username, password)
    
            ' The remote command to execute
            Dim command As String = "dir *.*"
    
            ' Some environment variables
            Dim environmentVariable As KeyValuePair(Of String, String) = New KeyValuePair(Of String, String)("MYVARIABLE", "MYVALUE")
    
            ' Create a session that will execute a remote command
            Using executeCommandSession As New ExecuteCommandSession(ssh)
              Dim commandOutputStream As Stream = Nothing
              Dim commandErrorStream As Stream = Nothing
    
              Try
    '             We obtain the output and error streams BEFORE starting the command so that we don't
    '               miss any output. 
    
    '             If the CommandOutputStream or the CommandErrorStream object is not taken,
    '               the component silently discards the incoming data. This might be desirable if
    '               the output and/or error text is not needed. 
    
                ' Get the command's output stream (standard output)
                commandOutputStream = executeCommandSession.GetOutputStream()
    
                ' Get the command's error stream (standard error)
                commandErrorStream = executeCommandSession.GetErrorStream()
    
                ' Now that we are setup the way we want, we can safely start the remote command 
    
                ' Start executing the specified command on the remote server passing the supplied environment variables to the server
                executeCommandSession.Connect(command, environmentVariable)
    
    '             Notice how we wrap the streams with StreamReader objects only after starting the command.
    '               This guards against the possibility of the StreamReader object calling Stream.Read() before
    '               we've started the command. 
    
                ' Wrap a stream reader around the output stream
                Dim outputReader As New System.IO.StreamReader(commandOutputStream)
    
                ' Wrap a stream reader around the error stream
                Dim errorReader As New System.IO.StreamReader(commandErrorStream)
    
                ' Read a line from the output and error at the same time
                Dim readOutputLineTask As Task(Of String) = outputReader.ReadLineAsync()
                Dim readErrorLineTask As Task(Of String) = errorReader.ReadLineAsync()
    
                Dim line As String
    
                ' While either the output or error streams haven't reached end-of-file
                Do While readOutputLineTask IsNot Nothing OrElse readErrorLineTask IsNot Nothing
                  ' If reading an output line has completed
                  If readOutputLineTask IsNot Nothing AndAlso readOutputLineTask.IsCompleted Then
                    ' Get the line
                    line = readOutputLineTask.Result
    
                    ' If we have a line
                    If line IsNot Nothing Then
                      ' Output it to the console
                      Console.WriteLine(line)
    
                      ' Read another line
                      readOutputLineTask = outputReader.ReadLineAsync()
                    Else
                      ' We've reached end-of-file. We don't want to read again 
                      readOutputLineTask = Nothing
                    End If
                  End If
    
                  ' If reading an error line has completed
                  If readErrorLineTask IsNot Nothing AndAlso readErrorLineTask.IsCompleted Then
                    ' Get the line
                    line = readErrorLineTask.Result
    
                    ' If we have a line
                    If line IsNot Nothing Then
                      ' Output it to the console
                      Console.WriteLine(line)
    
                      ' Read another line
                      readErrorLineTask = errorReader.ReadLineAsync()
                    Else
                      ' We've reached end-of-file. We don't want to read again 
                      readErrorLineTask = Nothing
                    End If
                  End If
                Loop
    
    '             Because we've processed the output stream until end-of-file, we are sure that
    '              the command has completed. No need to wait. 
    '
    '               However, if accessing the exit status or possible exit signal of the command
    '               is important to the application, it is best to wait until the command has signaled it
    '               has completed. At that point, the exit information will have been received. 
    
                ' Wait until the command has completed
                executeCommandSession.SessionCompletedWaitHandle.WaitOne()
    
    '             Some servers will return exit information like the return code and the 'signal'
    '              if the command fails. 
    
                Dim exitStatus As Nullable(Of Integer) = executeCommandSession.ExitStatus
                Console.WriteLine("Command exited with status {0}",If(exitStatus.HasValue, exitStatus.ToString(), "(null)"))
    
                Dim exitSignal As SSHChannelExitSignal = executeCommandSession.ExitSignal
                If exitSignal IsNot Nothing Then
                  Console.WriteLine("Command exited with signal {0}: {1}", exitSignal.SignalName, exitSignal.ErrorMessage)
                End If
              Catch e1 As SSHChannelRequestFailedException
    '             This exception is thrown by ExecuteCommandSession.Connect(). The most common
    '             * cause is the authenticated user does not have the rights to execute commands
    '             * on the server. 
              Finally
                If commandOutputStream IsNot Nothing Then
                  commandOutputStream.Close()
                  commandOutputStream = Nothing
                End If
    
                If commandErrorStream IsNot Nothing Then
                  commandErrorStream.Close()
                  commandErrorStream = Nothing
                End If
              End Try
            End Using
    
          Finally
            ' Always make sure to disconnect from the server when the connection is no longer needed
            ssh.Disconnect()
          End Try
        End Sub
      End Class
    End Namespace
     Send data to standard input

    The output of the command can be captured. Here a technique using asynchronous reading is used in order to read output and error text at the same time.

    using System.IO;
    
    using Xceed.SSH.Client;
    using Xceed.SSH.Core;
    using Xceed.SSH.Protocols;
    using Xceed.FileSystem;
    
    namespace DocumentationExamples.SSH
    {
      public class ExecuteCommandSession2
      {
        public void Example()
        {
          string host = "localhost";
          string username = "normal1";
          string password = "normal1";
    
          SSHClient ssh = new SSHClient();
    
          // Connect to the host
          ssh.Connect( host );
    
          try
          {
            // Log in
            ssh.Authenticate( username, password );
    
            // The remote command to execute
            string command = "copy Test.txt BackTest.txt /-Y";
    
            // Create a session that will execute a remote command
            using( ExecuteCommandSession executeCommandSession = new ExecuteCommandSession( ssh ) )
            {
              // Get the command's output stream (standard output/stdout)
              Stream commandOutputStream = executeCommandSession.GetOutputStream();
    
              // Start executing the specified command on the remote server
              executeCommandSession.Connect( command );
    
              // Wrap the output stream into a stream reader
              System.IO.StreamReader reader = new System.IO.StreamReader( commandOutputStream );
    
              string line;
    
              /* We expect to receive the text
    
                 Overwrite BackTest.txt? (Yes/No/All):
    
                 and then the remote console will wait for input. We can't call ReadLine() to get
                 the question since it does not contain a newline, we would wait forever.
    
                 Since we know what we're going to receive, we'll just go-ahead and send the response immediately. */
    
              // Get the command's input stream (standard input/stdin)
              Stream commandInputStream = executeCommandSession.GetInputStream();
    
              // Wrap the input stream into a stream writer
              StreamWriter writer = new StreamWriter( commandInputStream );
    
              // Answer the overwrite query
              writer.WriteLine( "y" );
              writer.Flush();
    
              // Read the next lines until we reach end-of-file
              while( ( line = reader.ReadLine() ) != null )
              {
                // Output the line
                Console.WriteLine( line );
              }
            }
          }
          catch( SSHChannelRequestFailedException )
          {
            /* This exception is thrown by ExecuteCommandSession.Connect(). The most common
             * cause is the authenticated user does not have the rights to execute commands
             * on the server. */
            }
          finally
          {
            // Always make sure to disconnect from the server when the connection is no longer needed
            ssh.Disconnect();
          }
        }
      }
    }
    Imports System.IO
    
    Imports Xceed.SSH.Client
    Imports Xceed.SSH.Core
    Imports Xceed.SSH.Protocols
    Imports Xceed.FileSystem
    
    Namespace DocumentationExamples.SSH
      Public Class ExecuteCommandSession2
        Public Sub Example()
          Dim host As String = "localhost"
          Dim username As String = "normal1"
          Dim password As String = "normal1"
    
          Dim ssh As New SSHClient()
    
          ' Connect to the host
          ssh.Connect(host)
    
          Try
            ' Log in
            ssh.Authenticate(username, password)
    
            ' The remote command to execute
            Dim command As String = "copy Test.txt BackTest.txt /-Y"
    
            ' Create a session that will execute a remote command
            Using executeCommandSession As New ExecuteCommandSession(ssh)
              ' Get the command's output stream (standard output/stdout)
              Dim commandOutputStream As Stream = executeCommandSession.GetOutputStream()
    
              ' Start executing the specified command on the remote server
              executeCommandSession.Connect(command)
    
              ' Wrap the output stream into a stream reader
              Dim reader As New System.IO.StreamReader(commandOutputStream)
    
              Dim line As String
    
    '           We expect to receive the text
    '
    '             Overwrite BackTest.txt? (Yes/No/All):
    '
    '             and then the remote console will wait for input. We can't call ReadLine() to get
    '             the question since it does not contain a newline, we would wait forever.
    '
    '             Since we know what we're going to receive, we'll just go-ahead and send the response immediately. 
    
              ' Get the command's input stream (standard input/stdin)
              Dim commandInputStream As Stream = executeCommandSession.GetInputStream()
    
              ' Wrap the input stream into a stream writer
              Dim writer As New StreamWriter(commandInputStream)
    
              ' Answer the overwrite query
              writer.WriteLine("y")
              writer.Flush()
    
              ' Read the next lines until we reach end-of-file
              line = reader.ReadLine()
              Do While line IsNot Nothing
                ' Output the line
                Console.WriteLine(line)
                line = reader.ReadLine()
              Loop
            End Using
          Catch e1 As SSHChannelRequestFailedException
    '         This exception is thrown by ExecuteCommandSession.Connect(). The most common
    '         * cause is the authenticated user does not have the rights to execute commands
    '         * on the server. 
          Finally
            ' Always make sure to disconnect from the server when the connection is no longer needed
            ssh.Disconnect()
          End Try
        End Sub
      End Class
    End Namespace