使用Plink.exe测试连接到C#中的SSH

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

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

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

我想要的是这样的:

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

这是我到目前为止的代码:

class Program { static void Main(string[] args) { ProcessStartInfo psi = new ProcessStartInfo(@"C:\Windows\System32\cmd"); 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:\putty\plink -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上使用其他人的解决方案,但它们似乎都没有为我工作,因为我不断得到这个挂起。 非常感谢提示。

编辑

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

所以我只想plink测试plink ,结果非常令人满意。

正如我在评论中所说,在发送exit命令之前不能使用ReadToEnd ,除非你想阻止 当前的 Thread。

实际上你可以在使用ReadToEnd之前发送一堆命令(包括exitlogout ),但我确实建议执行Read asynchrounusly,因为它更强大。

现在有几种方法可以对流进行异步读取。


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

  • OutputDataReceived
  • ErrorDataReceived

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


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

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

  public string RequestInfo(string remoteHost, string userName, string password, string[] lstCommands) { m_szFeedback = "Feedback from: " + remoteHost + "\r\n"; 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 + "\r\n"; } } } 

因此,如果要获取远程主机调用的用户目录的内容:

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

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

您也可能想要清理输出字符串。 在我的情况下,我发送给远程主机的命令会回显到输出中,从而出现在返回字符串中。

嘿上面的代码部分为我工作,但它是很好的帮助我juts取代承包商参数如下

const string PLINK_PATH = @“C:\ Program Files(x86)\ PuTTY \ plink.exe”;

  Process p = new Process(); // Redirect the output stream of the child process. p.StartInfo.UseShellExecute = false; p.StartInfo.RedirectStandardInput = true; p.StartInfo.RedirectStandardOutput = true; p.StartInfo.RedirectStandardError = true; p.StartInfo.FileName = PLINK_PATH; p.StartInfo.Arguments = String.Format(" -ssh {0}@{1} -pw {2}", userName, remoteHost, password); 

希望这有助于上面的代码….