C #: проблема с запуском команд оболочки - PullRequest
3 голосов
/ 03 мая 2009

Я пытаюсь заставить анализатор 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);

EDIT: С этим текущим кодом он генерирует исключение в коде без вывода.

Ответы [ 6 ]

5 голосов
/ 06 мая 2009

Задать путь к рабочему каталогу

var p = new Process
            {
                StartInfo = new ProcessStartInfo("php", path)
                {
                    RedirectStandardOutput = true,
                    RedirectStandardError = true,
                    UseShellExecute = false,
                    CreateNoWindow = true,
                    WorkingDirectory = workingDir
                }
            };
5 голосов
/ 03 мая 2009

Проблема в том, что вы читаете вывод до завершения программы. Вам нужно дождаться завершения программы, чтобы обработать вывод. В противном случае вы будете обрабатывать вывод до завершения анализа. Добавьте следующую строку.

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

РЕДАКТИРОВАТЬ ОП сказал, что они все еще имеют проблемы.

Попробуйте удалить часть команды CMD. Просто запустите команду PHP напрямую. Также может быть полезно разрешить создание окна для целей отладки, чтобы вы могли видеть любые ошибки, которые могут возникнуть при выполнении команды.

2 голосов
/ 04 мая 2009

Самый надежный способ вызвать процесс и зафиксировать его вывод или ошибку - попробовать его следующим образом:

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);
1 голос
/ 03 мая 2009

Вам необходимо добавить p.WaitForExit (); после p.Start (); иначе вывод не готов, когда вы пытаетесь прочитать его.

1 голос
/ 03 мая 2009

ReadToEnd() просто читает все содержимое потока, как оно есть на тот момент времени. Учитывая, что вы вызываете это сразу после Start(), поток скорее всего пуст. У вас есть несколько вариантов

  • Позвоните ReadLine() вместо этого, но это будет читать только одну строку
  • p.WaitForExit(), затем позвоните ReadToEnd(), но я не уверен, что это держит поток открытым. Если это так, то это ваш лучший вариант.
0 голосов
/ 03 мая 2009

Есть ли причина, по которой вы запускаете php через cmd? Разве вы не можете просто выполнить это напрямую?

По моему опыту, выполнение процессов через .NET является худшим способом выполнения другого процесса. fork () под unix на удивление намного лучше. У меня было так много проблем, что я советую вам STRONGLY рассмотреть возможность Process.BeginOutputReadLine () и пройти асинхронный маршрут в вашем чтении. ReadToEnd и ReadToLine могут зависать бесконечно, особенно если у вас есть длинный вывод для захвата.

Я бы вставил пример, но он довольно длинный.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...