ScpClient missing methods

Jan 18, 2013 at 3:36 PM

Hi, why ScpClient doesnt have the following functionality ? (cant be done or is just pending?)

  • CreateDirectory
  • DeleteDirectory
  • DeleteFile
  • MoveFile
  • ExistFile
  • ExistDirectory
  • ListDirectory

There is currently any work-around ?

Coordinator
Jan 18, 2013 at 3:43 PM

Well,

The main reason is that I am not sure if its possible, since I am not familiar with this protocol so well.

The only specification and examples I could find is for Upload and Download file(s) or Directories so that's what I implemented.

If you happened to know the SCP protocol specification for how to do those operations I would try to implement them then.

 

Hope it helps,

Thanks,

Oleg

Jan 18, 2013 at 6:49 PM

Hi, im sorry i dont know much about the SCP, the workaround i find is to create a SshShell and send commands, here are how i implement it:

 

        /// <summary>
        /// Runs the command.
        /// </summary>
        /// <param name="commandText">The command text.</param>
        /// <exception cref="IT.FileTransfer.FileTransferException"></exception>
        void RunCommand(string commandText)
        {
            using (SshClient client = new SshClient(Host, User, Password))
            {
                client.Connect();

                using (SshCommand cmd = client.RunCommand(commandText))
                {
                    if (cmd.ExitStatus != 0)
                        throw new FileTransferException(cmd.Error)
                        {
                            RemotePath = commandText
                        };
                }
            }
        }

        /// <summary>
        /// Crea un directorio en el host remoto.
        /// </summary>
        /// <param name="remoteDirectory">El path del directorio remoto.</param>
        public override void CreateDirectory(string remoteDirectory)
        {
            RunCommand(@"mkdir " + remoteDirectory);
        }

        /// <summary>
        /// Elimina un directorio en el host remoto.
        /// </summary>
        /// <param name="remoteDirectory">El path del directorio remoto.</param>
        public override void DeleteDirectory(string remoteDirectory)
        {
            if (DeleteRecursive)
                RunCommand(@"rm -r " + remoteDirectory);
            else
                RunCommand(@"rmdir " + remoteDirectory);
        }

        /// <summary>
        /// Elimina un archivo en el host remoto.
        /// </summary>
        /// <param name="remoteFile">El archivo remoto a eliminar.</param>
        public override void DeleteFile(string remoteFile)
        {
            RunCommand(@"rm " + remoteFile);
        }

        /// <summary>
        /// Mueve un archivo, posiblemente cambiando el nombre en el host remoto.
        /// </summary>
        /// <param name="currentRemoteFile">El archivo a mover.</param>
        /// <param name="newRemoteFile">La nueva ubicaci�n y nombre.</param>
        public override void MoveFile(string currentRemoteFile, string newRemoteFile)
        {
            RunCommand(@"mv " + currentRemoteFile + " " + newRemoteFile);
        }

        /// <summary>
        /// Determina si existe el archivo en el host remoto.
        /// </summary>
        /// <param name="remoteFile">El archivo remoto.</param>
        /// <returns>
        ///   <c>true</c> si existe, <c>false</c> caso contrario.
        /// </returns>
        public override bool ExistFile(string remoteFile)
        {
            try
            {
                RunCommand(@"ls " + remoteFile);

                return true;
            }
            catch (FileTransferException)
            {
                return false;
            }
        }

        /// <summary>
        /// Determina si existe el directorio en el host remoto.
        /// </summary>
        /// <param name="remoteDirectory">El directorio remoto.</param>
        /// <returns>
        ///   <c>true</c> si existe, <c>false</c> caso contrario.
        /// </returns>
        public override bool ExistDirectory(string remoteDirectory)
        {
            try
            {
                RunCommand(@"cd " + remoteDirectory);

                return true;
            }
            catch (FileTransferException)
            {
                return false;
            }
        }

        /// <summary>
        /// Obtiene un listado de archivos del directorio remoto.
        /// </summary>
        /// <param name="remoteDirectory">El directorio remoto a consultar.</param>
        /// <returns>
        /// Un listado de archivos.
        /// </returns>
        /// <exception cref="IT.FileTransfer.FileTransferException"></exception>
        public override string[] ListDirectory(string remoteDirectory)
        {
            using (SshClient client = new SshClient(Host, User, Password))
            {
                client.Connect();

                using (SshCommand cmd = client.RunCommand("ls -l " + remoteDirectory))
                {
                    if (cmd.ExitStatus != 0)
                        throw new FileTransferException(cmd.Error)
                        {
                            RemotePath = remoteDirectory
                        };

                    return cmd.Result.Split(new string[] { "\n", "\r" }, StringSplitOptions.RemoveEmptyEntries);
                }
            }
        }

Coordinator
Jan 18, 2013 at 7:18 PM

Well, yea, it could be as workaround but basically what it will do is will duplicate some code, since I have similar operations available in SftpClient already.

I just strive for client to implement client features that are supported by protocol, at least at this moment.

 

Thanks,

Oleg

Jan 21, 2013 at 12:46 PM

Thats ok, its just i have a interface to implement, i have the Sftp implementation all ok, and just in case have made a Scp implememntation with this header :)

    /// <summary>
    /// Implementa transferencia de archivos mediante SSH Secure Copy.
    /// ------------------------------------------------------------------
    /// IMPORTANTE: Siempre que sea posible utilizar SFTP en lugar de SCP.
    /// ------------------------------------------------------------------
    /// </summary>
    [Obsolete("IMPORTANTE: Siempre que sea posible utilizar SFTP en lugar de SCP.")]
    public class ScpFileTransfer : FileTransferBase

It says basically dont use this if you can use SFTP.

Feb 20, 2013 at 8:39 AM
well all this commands can be put into the base class...
Coordinator
Feb 20, 2013 at 1:36 PM
Hi,

Yes, I agree but I just dont want to overcrowd class with method, since SFTP class for example will have a lot of methods to support SFTP and other commands for SCP, shell, command exaction will be simply lost, so I guess for now I just would keep it in separate classes.

Thanks,
Oleg