C#:运行shell命令时出现问题

时间:2009-05-03 14:17:26

标签: c# php shell

我正在尝试让PHP解析器运行一个页面,然后将结果返回给我的服务器,但是当我通过我的代码运行命令时,它什么都不返回。我知道命令是正确的,因为如果我用相同的路径手动运行它,它工作正常。继承我的代码:

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);

编辑: 使用此当前代码,它会在没有输出的代码中抛出异常。

6 个答案:

答案 0 :(得分:5)

问题是您在程序完成之前正在读取输出。您需要等待程序退出才能处理输出。否则,您将在解析完成之前处理输出。添加以下行。

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

编辑 OP表示他们仍有问题。

尝试删除命令的CMD部分。只需直接运行PHP命令即可。允许创建用于调试目的的窗口也是有益的,这样您就可以看到运行命令时可能出现的任何错误。

答案 1 :(得分:5)

设置WorkingDirectory路径

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

答案 2 :(得分:2)

调用进程并捕获其输出或错误的最强大的方法是尝试以下方式:

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);

答案 3 :(得分:1)

ReadToEnd()只是在那个时间点读取流的全部内容。鉴于您在Start()之后立即调用此流,因此该流可能为空。你有几个选择

  • 改为调用ReadLine(),但这只会读取一行
  • p.WaitForExit()然后拨打ReadToEnd(),但我不确定这会让流保持打开状态。如果是这样,那么这是您最好的选择。

答案 4 :(得分:1)

你需要添加p.WaitForExit();在p.Start()之后;否则当您尝试读取时输出尚未就绪。

答案 5 :(得分:0)

你有没有理由通过cmd运行php?你不能直接执行它吗?

根据我的经验,通过.NET执行进程是执行另一个进程的最糟糕方式。 unix下的fork()非常好。我有很多问题,我的建议是强烈考虑查看Process.BeginOutputReadLine()并在阅读中走异步路线。 ReadToEnd和ReadToLine可以无限期挂起,特别是如果要捕获冗长的输出。

我会粘贴一个例子,但它相当冗长。