title: Reading and processing command output line by line in SSH.NET
body: <p>I am working on a home project that needs to execute some commands via SSH, read back the responses and display them on a web page. A lot of the time it does work, but now and then i get some inconsistent behavior, for example certain lines of output are missed that would instruct on what to do next, this results in a hung session, and a requirement to restore IIS.</p>
  
  <p>I have included the code below, like I said I am not a full time developer, so its gonna be a mess, but hopefully someone can point me in the right direction to understand what i got so wrong, and what i need to change, i wont learn if you just past code snippets up, id much rather attempt to try and fix what i have.</p>
  
  <pre><code>using (SshClient ssh = new SshClient("192.168.0.119", "x", "x."))
  {
      ssh.Connect();
      ShellStream shell = ssh.CreateShellStream("Tail", 0, 0, 0, 0, 1024);
      StreamWriter wr = new StreamWriter(shell);
      StreamReader rd = new StreamReader(shell);
      wr.AutoFlush = true;
      if (extract)
      {
          Console.WriteLine("Downloading DataZIP");
          ssh.RunCommand("wget " + zipURL);
      }
  
      bool reading = shell.CanRead;
      wr.WriteLine("cd " + remoteFilePath + packagename + " &amp;&amp; docker build -t dockerfile .");
  
      while (reading)
      {
          Clients.Caller.builderOut(shell.ReadLine().ToString());
          if (shell.ReadLine().ToString().Contains("Successfully"))
          {
              Clients.Caller.builderOut("Build Complete");
              reading = false;
          }
          if (shell.ReadLine().ToString().Contains("returned a non-zero code: "))
          {
              goto end;
          }
      }
  
      if (data.Type == TemplateType.Data)
      {
          wr.WriteLine("cd " + remoteFilePath + packagename + " &amp;&amp; docker tag dockerfile " + data.Repository + "/" + data.packagename.ToLower() + ":data.Type");
          wr.WriteLine("cd " + remoteFilePath + packagename + " &amp;&amp; docker push " + data.Repository + "/" + data.packagename.ToLower() + ":data.Type");
      }
  
      reading = shell.CanRead;
      while (reading)
      {
          Clients.Caller.builderOut("Pushing this will take a moment");
          if (shell.ReadLine().ToString().Contains("digest:"))
          {
              Clients.Caller.builderOut("Pushed");
              reading = false;
          }
      }
  
      Clients.Caller.builderOut("End");
      ssh.Disconnect();
      ssh.Dispose();
  }
  </code></pre>
  
  <p><strong>What I think I got wrong</strong><br>
  I think I get these errors due to the way I'm reading the console output. I think that that data changes so fast we miss some:</p>
  
  <pre><code>while (reading)
  {
      Clients.Caller.builderOut(shell.ReadLine().ToString());
      if (shell.ReadLine().ToString().Contains("Successfully"))
      {
          Clients.Caller.builderOut("Build Complete");
          reading = false;
      }
      if (shell.ReadLine().ToString().Contains("returned a non-zero code: "))
      {
          goto end;
      }
  }
  </code></pre>
  
  <p>So using that each of the 3 checks on the output could I think be be missing some of the lines, as the output is quite speedy, while its reading the value changes so the next check has different init data to check, and thus we skip over what would otherwise be the exit lines or next job lines.</p>