0

I am trying to upload file with ScpClient, however, I need to run a command first. I do not find any "write/run" method in ScpClient. Is there any way to do it?

private void upload_Click(object sender, EventArgs e)
{
    var auth1 = new PasswordAuthenticationMethod(username.Text, password.Text);
    var auth2 = new KeyboardInteractiveAuthenticationMethod(username.Text);
    ConnectionInfo conInfo = new ConnectionInfo(host.Text, username.Text, auth1, auth2);

    string source = @"C:\Users\User\Desktop\111.txt";
    string destination = @"/flash/data0";


    scpclient = new ScpClient(conInfo);
    scpclient.Connect();
    /*
    need to run a command 
    */        
    FileInfo file = new FileInfo(source);
    scpclient.Upload(file, destination);           
}
2
  • 1
    please share code snippet what ever you already tried and specify which version of c# you are use ? Commented Jan 7, 2020 at 7:07
  • 1
    I upload the part of code I tried before. Commented Jan 7, 2020 at 8:54

2 Answers 2

2

I assume you're using SSH.NET. Then you might try to reuse your connection and instantiate SshClient to run commands:

    var auth1 = new PasswordAuthenticationMethod(username.Text, password.Text);
    var auth2 = new KeyboardInteractiveAuthenticationMethod(username.Text);
    ConnectionInfo conInfo = new ConnectionInfo(host.Text, username.Text, auth1, auth2);
...
        //first you run your command
    var sshClient = new SshClient(conInfo);
    sshClient.Connect();
    var cmd = sshClient.RunCommand("ls");
    var r = cmd.Execute();

    //then you reuse credentials and upload your file

    var scpclient = new ScpClient(conInfo);
    scpclient.Connect(); // note you have to .connect() for the second time. this is due to library not providing any obvious ways to share session between clients
    /*
    need to run a command 
    */
    FileInfo file = new FileInfo("d:\\1.txt");
    scpclient.Upload(file, "~");
}

the way library is written seems to force into establishing two connections here, this can probably be overcome by inheriting from BaseClient and implementing your actions (most likely you just need to copy relevant methods from respective classes)


UPD as we already established, you want to keep your connection alive between operations, and therefore avoid doing the above. This is somewhat tricky as the library hides internal Session object and does not allow you to reuse it. You however can still inherit from one of the clients (ScpClient seemed like a good base to start) and implement the CreateCommand method like so:

public class RunAndUpload : ScpClient
{   
    public RunAndUpload(ConnectionInfo connectionInfo)
            : base(connectionInfo)
    {
    }

    public SshCommand CreateCommand(string commandText)
    {
        var pi = typeof(RunAndUpload).GetProperty("Session", BindingFlags.NonPublic | BindingFlags.Instance);
        var command = (SshCommand)typeof(SshCommand).GetConstructors(BindingFlags.NonPublic | BindingFlags.Instance)[0].Invoke(new object[] {pi.GetValue(this), commandText, this.ConnectionInfo.Encoding} );       
        return command;
    }
}

you will notice I had to opt for reflection just to instantiate the SshCommand (as it's constructor is internal to the library and normally would not be exposed). Once you past the stage of obtaining a command instance - it should all be smooth from there:

    using(var sshClient = new RunAndUpload(conInfo)) {
        sshClient.Connect();        
        var cmd = sshClient.CreateCommand("ls");
        var r = cmd.Execute();
        FileInfo file = new FileInfo("d:\\1.txt");
        sshClient.Upload(file, "1.txt");
    }

hopefully that works for you

Sign up to request clarification or add additional context in comments.

12 Comments

Can I use SshClient to upload a file? I cannot find this method in SshClient, therefore, I choose ScpClient. However, I need to run a command before I upload it.
I updated the answer. It seems you cannot use one client class for both actions, therefore you have to go connect twice - first to execute commands and then to upload files
Do you require both actions performed under same SSH session though?
Yes, I need to do it under same SSH session.
Is it possible to use ShellStream instead of Sshcommand? I do not know why the program will stuck when the code run to "var cmd = sshClient.CreateCommand("ls");".
|
0

SSH.NET is limited in some OpenSSH keys for this reason I have created a custom version of Microsoft.DevTunnels.Ssh to solve my issues.

check this one

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.