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
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.
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....