在 C# 中使用 Plink.exe 连接到 SSH 的测试 [英] Testing using Plink.exe to connect to SSH in C#

查看:49
本文介绍了在 C# 中使用 Plink.exe 连接到 SSH 的测试的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试通过 plink.exe 连接到 unix 终端.目标是让我可以将文本读回字符串.

Im trying to connect to a unix terminal via plink.exe. The goal is so that I can read the text back into a string.

我的困境是我工作的银行使用旧的 as400 类型系统,我们通常通过 putty 访问该系统.我正在尝试开发一个自动化套件,该套件将与系统交互并运行作业并分析输出等.

My dilema is that the bank I work for uses an old as400 type system that we normally access through putty. I'm trying to develop an automation suite that will interface with the system and run jobs and analyse the outputs etc.

所以我想我会通过 C# 使用 plink.如果我通过命令提示符运行代码,我会(大致)得到我需要的文本.然而,我在我的 C# 代码中遇到了一个问题,它只是挂起,我从来没有得到响应.

So I figured I'd use plink through C#. If I run the code via Command prompt I get (roughly) the text I need back. However im suffering a problem in my C# code in that it just hangs and I never get a reponse.

我想要的是这样的:

连接到服务器输入命令回读画面//更多命令等

Connect to server Input command Read back screen //More Commands etc

这是我目前的代码:

class Program
{
    static void Main(string[] args)
    {

        ProcessStartInfo psi = new ProcessStartInfo(@"C:WindowsSystem32cmd");
        psi.RedirectStandardInput = true;
        psi.RedirectStandardOutput = true;
        psi.WindowStyle = System.Diagnostics.ProcessWindowStyle.Normal;
        psi.UseShellExecute = false;
        psi.CreateNoWindow = false;

        Process process = Process.Start(psi);
        string cmdForTunnel = @"c:puttyplink -ssh jonkers@bankhq -pw automationhero";
        process.StandardInput.WriteLine(cmdForTunnel);
       // process.WaitForExit();
        Thread.Sleep(30000);
        string output = process.StandardOutput.ReadToEnd();

        Console.WriteLine(output);

        //DoBusinessLogic();
        process.StandardInput.WriteLine("logout");
        Thread.Sleep(10000);

        if (process.HasExited)
        {
            process.Close();
            process.Dispose();
        } 
    }
}

我不太确定问题出在哪里,因为正如我所说,我已经通过命令行测试了使用 plink,但上面的解决方案只是挂起.我试过在 stackoverflow 上使用其他人的解决方案,但似乎没有一个对我有用,因为我一直在解决这个问题.非常感谢您的提示.

Im not really sure where the issues lie because as I say ive tested in using plink through command line, but with my solution above it just hangs. Ive tried using other peoples solutions on stackoverflow but none of them seem to work for me as I keep getting this hang. And tips would be much appreciated.

编辑

我现在决定使用 Renci Sharp SSH 库并围绕此构建我自己的框架.效果更好.

I've now decided to use the Renci Sharp SSH library and have build my own framework around this. It works much better.

推荐答案

所以我只是想自己测试 plink 并且结果非常令人满意.

So I just wanted to test plink myself and well it's result were pretty pleasing.

正如我在评论中所说的,你不能使用 ReadToEnd before 你发送 exit 命令,除非你想阻止您的当前主题.

As I said in the comments you can't use ReadToEnd before you send the exit command, unless you want to block your current Thread.

实际上你可以在使用 ReadToEnd 之前发送一堆命令(包括 exitlogout),但我确实建议异步读取,因为它更健壮.

Actually you could just send a bunch of commands (including the exit or logout) before engaging the ReadToEnd, but I did suggest to do the Read asynchrounusly as it is more robust.

现在有几种方法可以异步读取流.

Now there are a few ways to do async reading of a stream.

Process 类实际上提供了在传入数据上引发的 Events.您可以为那些 Events 创建处理程序.这些事件是:

The Process class actually provides Events that are raised on incoming data. You could create handlers for those Events. These Events are:

  • OutputDataReceived
  • ErrorDataReceived

他们的事件处理程序提供包含数据的字符串.

Their event handlers provide strings containing the data.

您可以使用 stdout/stdin 的 StreamReader 实例的 BeginRead.

You could use the BeginRead of the StreamReader instances of stdout/stdin.

但在这里我提供了一个代码示例,它使用简单的多线程以更粗略的方式完成:

But here I provide a code sample that does it in a more crude way using simple multi-threading:

  public string RequestInfo(string remoteHost, string userName, string password, string[] lstCommands) {
        m_szFeedback = "Feedback from: " + remoteHost + "
";

        ProcessStartInfo psi = new ProcessStartInfo()
        {
            FileName = PLINK_PATH, // A const or a readonly string that points to the plink executable
            Arguments = String.Format("-ssh {0}@{1} -pw {2}", userName, remoteHost, password),
            RedirectStandardError = true,
            RedirectStandardOutput = true,
            RedirectStandardInput = true,
            UseShellExecute = false,
            CreateNoWindow = true
        };

        Process p = Process.Start(psi);

        m_objLock = new Object();
        m_blnDoRead = true;

        AsyncReadFeedback(p.StandardOutput); // start the async read of stdout
        AsyncReadFeedback(p.StandardError); // start the async read of stderr

        StreamWriter strw = p.StandardInput;

        foreach (string cmd in lstCommands)
        {
            strw.WriteLine(cmd); // send commands 
        }
        strw.WriteLine("exit"); // send exit command at the end

        p.WaitForExit(); // block thread until remote operations are done
        return m_szFeedback;
    }

    private String m_szFeedback; // hold feedback data
    private Object m_objLock; // lock object
    private Boolean m_blnDoRead; // boolean value keeping up the read (may be used to interrupt the reading process)

    public void AsyncReadFeedback(StreamReader strr)
    {
        Thread trdr = new Thread(new ParameterizedThreadStart(__ctReadFeedback));
        trdr.Start(strr);
    }
    private void __ctReadFeedback(Object objStreamReader)
    {
        StreamReader strr = (StreamReader)objStreamReader; 
        string line;          
        while (!strr.EndOfStream && m_blnDoRead) 
        {
            line = strr.ReadLine();
            // lock the feedback buffer (since we don't want some messy stdout/err mix string in the end)
            lock (m_objLock) { m_szFeedback += line + "
"; }
        }
    }

所以如果你想获取远程主机调用的用户目录的内容:

So if you want to get the contents of the user directory of a remote host call:

String feedback = RequestInfo("remote.ssh.host.de", "user", "password", new string[] { "ls -la" });

显然,您替换了自己的地址、凭据和命令列表.

Obviously you substitute your own address, credentials and command-list.

此外,您可能还想清理输出字符串.例如.在我的例子中,我发送到远程主机的命令被回显到输出中,因此出现在返回字符串中.

Also you might want to clean the output string. e.G. in my case the commands I send to the remotehost are echoed into the output and thus appear in the return string.

这篇关于在 C# 中使用 Plink.exe 连接到 SSH 的测试的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆