C#: Problem running shell commands

2020-07-23 05:57发布

问题:

I'm trying to get the PHP parser to run a page and then return the results to my server, however when I run the command via my code, it returns nothing. I know the command is correct because if I run it manually with the same path, it works fine. Heres my code:

var p = new Process
{
      StartInfo = new ProcessStartInfo("C:\\xampp\\php\\php.exe", path)
      {
            RedirectStandardOutput = true,
            RedirectStandardError = true,
            UseShellExecute = false,
            CreateNoWindow = true
      }
};
var output = new StringWriter();
var error = new StringWriter();
p.OutputDataReceived += (sender, args) => output.WriteLine(args.Data);
p.ErrorDataReceived += (sender, args) => error.WriteLine(args.Data);
p.Start();
p.BeginOutputReadLine();
p.BeginErrorReadLine();
p.WaitForExit();
if (p.ExitCode != 0)
{
      throw new Exception(string.Format(
          "PHP failed with the following output:{0}{1}",
      /* {0} */ Environment.NewLine,
      /* {1} */ error.GetStringBuilder().ToString()));
}
var res = output.GetStringBuilder().ToString();
Console.WriteLine(res);

EDIT: With this current code, it throws the exception in the code with no output.

回答1:

Set WorkingDirectory Path

var p = new Process
            {
                StartInfo = new ProcessStartInfo("php", path)
                {
                    RedirectStandardOutput = true,
                    RedirectStandardError = true,
                    UseShellExecute = false,
                    CreateNoWindow = true,
                    WorkingDirectory = workingDir
                }
            };


回答2:

The problem is that you are reading the output before the program finishes. You need to wait for program exit to process the output. Otherwise you'll be processing the output before the parse is complete. Add the following line in.

p.Start();
p.WaitForExit();  // New line

EDIT OP said they are still having problems.

Try removing the CMD portion of the command. Just run the PHP command directly. It also may be beneficial to allow the creation of a window for debugging purposes so you can see any errors that may come out of running the command.



回答3:

The most robust way to invoke the process and capture its output or error would to try it the following way:

var p = new Process {
    StartInfo = new ProcessStartInfo("php", path) {
        RedirectStandardOutput = true,
        RedirectStandardError = true,
        UseShellExecute = false,
        CreateNoWindow = true
    }
};
var output = new StringWriter();
var error = new StringWriter();
p.OutputDataReceived += (sender, args) => output.WriteLine(args.Data);
p.ErrorDataReceived += (sender, args) => error.WriteLine(args.Data);
p.Start();
p.BeginOutputReadLine();
p.BeginErrorReadLine();
p.WaitForExit();
if (p.ExitCode != 0) {
    throw new Exception(string.Format(
        "PHP failed with the following output:{0}{1}",
        /* {0} */ Environment.NewLine,
        /* {1} */ error.GetStringBuilder().ToString()));
}
var res = output.GetStringBuilder().ToString();
Console.WriteLine(res);


回答4:

ReadToEnd() just reads the entire contents of the stream as they are at that point in time. Given that you're calling this immediately after Start(), the stream is likely empty. You have a couple of options

  • Call ReadLine() instead, but this will only read one line
  • p.WaitForExit() then call ReadToEnd(), but I am not certain this keeps the stream open. If this does, then this is your best option.


回答5:

You need to add p.WaitForExit(); after the p.Start(); else the output is not ready when you try to read it.



回答6:

Is there a reason you're running php through cmd? Can't you just execute it directly?

It has been my experience that executing processes through .NET is the worst way to execute another process. fork() under unix is amazingly much better. I have had so many issues that my advice is that you STRONGLY consider looking at Process.BeginOutputReadLine() and go the asynchronous route in your reading. ReadToEnd and ReadToLine can hang indefinitely especially if you have lengthy output to capture.

I would paste an example but it is rather lengthy.



标签: c# php shell