Testing using Plink.exe to connect to SSH in C#

前端 未结 2 1777
渐次进展
渐次进展 2020-12-11 12:18

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.

My dilema is that the bank I work for uses an old

相关标签:
2条回答
  • 2020-12-11 12:28

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

    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.

    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.


    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.


    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 + "\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"; }
            }
        }
    

    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.

    0 讨论(0)
  • 2020-12-11 12:49

    Hey the above code worked partially for me but it was good help i juts replaced the contractor parameters as follows

    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);
    

    Hope this helps with above code....

    0 讨论(0)
提交回复
热议问题