简体   繁体   English

C# 使用 ScpClient 运行命令

[英]C# Running command with ScpClient

I am trying to upload file with ScpClient, however, I need to run a command first.我正在尝试使用 ScpClient 上传文件,但是,我需要先运行一个命令。 I do not find any "write/run" method in ScpClient.我在 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);           
}

I assume you're using SSH.NET .我假设您使用的是SSH.NET Then you might try to reuse your connection and instantiate SshClient to run commands:然后你可以尝试重用你的连接并实例化 SshClient 来运行命令:

    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)库的编写方式似乎强制在这里建立两个连接,这可能可以通过从BaseClient继承并实现您的操作来克服(很可能您只需要从相应的类中复制相关方法)


UPD as we already established, you want to keep your connection alive between operations, and therefore avoid doing the above. UPD正如我们已经建立的那样,您希望在操作之间保持连接活跃,因此避免执行上述操作。 This is somewhat tricky as the library hides internal Session object and does not allow you to reuse it.这有点棘手,因为库隐藏了内部Session对象并且不允许您重用它。 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:但是,您仍然可以从其中一个客户端继承( ScpClient似乎是一个很好的基础)并像这样实现CreateCommand方法:

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).你会注意到我不得不选择反射来实例化SshCommand (因为它的构造函数是库内部的,通常不会暴露)。 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希望这对你有用

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM