2

I'm new to C# (and development in general). I need to write a method in C# that will execute following via console: - install Newman; - execute postman Run.

I've created a method as below (I tried 2 options: ReadToEnd and WaitForExit), but it seems to stuck at each of these steps.

Any help how to make this to execute both commands in sequence (1st needs to finish before 2nd start) and exit after 2nd command executed fully?

Thanks in advance.

    public string Runner ()
    {
        string readOutput = null;
        var psiNpm = new ProcessStartInfo
        {
            FileName = "cmd",
            RedirectStandardOutput = true,
            RedirectStandardInput = true,
            UseShellExecute = false
        };
        var pNpmRun = Process.Start(psiNpm);
        pNpmRun.StandardInput.WriteLine($"npm install -g newman");
        pNpmRun.WaitForExit();
        //pNpmRun.StandardOutput.ReadToEnd();
        pNpmRun.StandardInput.WriteLine($"newman run " +
            $"\"C:\\Postman\\Test.postman.json\" " +
            $"--folder \"TestSearch\" " +
            $"--environment \"C:\\Postman\\postman_environment.json\" " +
            $"--disable-unicode");
        pNpmRun.StandardOutput.ReadToEnd();
        pNpmRun.WaitForExit();
        return readOutput = pNpmRun.StandardOutput.ReadLine();
    }
haldo
  • 14,512
  • 5
  • 46
  • 52
KVN
  • 863
  • 1
  • 17
  • 35
  • I believe if you use both StandardInput and StandardOutput you must [do so asynchronously](https://stackoverflow.com/a/1044189/22437) to avoid deadlocks. – Dour High Arch Apr 08 '19 at 23:19

1 Answers1

4

Try writing an exit command to your cmd input stream.

The issue, is the commands you sent (npm, newman) are executing, then control is returning to the shell (cmd), which is then waiting for more user input to be sent. You need to tell it to quit by sending "exit". You should only have 1 WaitForExit call. The WaitForExit is waiting for the cmd process to exit, not the individual commands you send to it.

Next, you should move ReadToEnd after the process has exited (after WaitForExit). Here is a question concering why: ReadToEnd from std output of process and waitforexit

So, something like this:

public string Runner ()
    {
        var psiNpm = new ProcessStartInfo
        {
            FileName = "cmd",
            RedirectStandardOutput = true,
            RedirectStandardInput = true,
            UseShellExecute = false
        };
        var pNpmRun = Process.Start(psiNpm);
        pNpmRun.StandardInput.WriteLine("npm install -g newman");
        pNpmRun.StandardInput.WriteLine("newman run " +
            "\"C:\\Postman\\Test.postman.json\" " +
            "--folder \"TestSearch\" " +
            "--environment \"C:\\Postman\\postman_environment.json\" " +
            "--disable-unicode");
        pNpmRun.StandardInput.WriteLine("exit");

        pNpmRun.WaitForExit();
        return pNpmRun.StandardOutput.ReadToEnd();

You might also consider adding a timeout to the WaitForExit. If these cmds get stuck for some reason your calling process is also going to get stuck waiting for them to complete. Usually best to eventually fail than have a bunch of hung processes. You could then kill the process if the timeout expires.

  var tenMin = 10 * 60 * 1000;
  if(pNpmRun.WaitForExit(tenMin)) {
    return pNpmRun.StandardOutput.ReadToEnd();
  } else {
    pNpmRun.Kill();
    throw new TimeoutException("Command didn't complete in 10 minute timeout");
  }

MarkPflug
  • 28,292
  • 8
  • 46
  • 54
  • Thanks @MarkPflug! That works as I need. BTW How do I set it up that it will fail and kill the process if the cmd stuck? – KVN Apr 09 '19 at 15:12
  • 1
    @KVN Updated with timeout example. Note that if the npm or newman processes are stuck, they will *not* be killed, only the cmd process. – MarkPflug Apr 09 '19 at 15:40
  • Thanks a lot @MarkPflug! – KVN Apr 09 '19 at 16:23
  • @KVN Another thing you should consider is what the behavior will be if the npm/newman commands fail for some reason. Presumably npm could fail if there was a network issue, etc. You should probably check the exit codes of your commands, and if they are non-zero (failures) then communicate that back to the caller by using "exit %errorlevel%". If you need help with that, probably best to open a new question. – MarkPflug Apr 09 '19 at 17:55
  • Thanks @MarkPflug. Actually, this is now my real problem, if there is an issue with newman execution - it just hangs and goes into failure/kill part of the IF. I have created another ticket for this (maybe you can help with that one too): https://stackoverflow.com/questions/55600299/how-to-handle-npm-newman-failure-hanging-when-executed-via-c-sharp-console – KVN Apr 09 '19 at 19:51
  • sorry @MarkPflug, seems like my current execution is always failing the WaitForExit, regardless if I specify 0ms or 10 mins, it always goes into the Process.Kill() part of the condition. But the newman command has executed within 2-5 sec. Any thoughts on what is happening (wrong) with it? I can create a new question if needed. – KVN Apr 10 '19 at 22:53