Search code examples
c#ioputtyplink

Capturing Plink output in C#


I am trying to use Plink to access information on a machine. I followed this tutorial:
http://www.mindfiresolutions.com/Creating-a-SSH-connection-using-plink-PuTTY-via-C-application-1760.ph

So far I am only using my program to just open up Plink, and I will be adding in the login information and such once I can at least get Plink to be openable in my program. I have this based on the tutorial:

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);
Thread.Sleep(3000);
string cmdForTunnel = "plink";
process.StandardInput.WriteLine(cmdForTunnel);
process.WaitForExit();
Thread.Sleep(10000);

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

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

But nothing is displayed, which bothers me. The command plink is supposed to display the help information on how to use the program (I will be replacing the command with something more useful later), but the command prompt remains empty. I also experimented by replacing plink with ipconfig, which also displayed nothing.

I know how to open up cmd myself and type in plink to access it. I want to replicate this action in my program.


Solution

  • You have many faults in your code:

    • You are redirecting an output, and you are not reading/processing/printing it (that's why "nothing is displayed")
    • Running plink by "typing" plink to cmd.exe is insane. You can run plink directly, avoiding cmd.exe completely (and even if you needed to use the cmd.exe, you should pass plink.exe to it on a command-line: /c path\plink.exe). And no, running it directly would not cause Plink to close instantly.
    • Calling WaitForExit() without reading the redirected output will deadlock your code once an output buffer fills. See Remarks section for ProcessStartInfo.RedirectStandardOutput. Alternatively, use process.StandardOutput.ReadToEnd() (it's like WaitForExit, but also reads the output). It's actually what the MSDN recommends in the previous link.
    • If you are going to execute one command only, using Plink, it's also better to pass the command on Plink command-line, rather than "typing" it to its (redirected) input:

      plink.exe -ssh user@host command
      

    See also answer to Testing using Plink.exe to connect to SSH in C#