Как получить вывод System.Diagnostics.Process?

Я запускаю ffmpeg следующим образом:

System.Diagnostics.Process p = new System.Diagnostics.Process();
p.StartInfo = new System.Diagnostics.ProcessStartInfo(ffmpegPath, myParams);
p.Start();
p.WaitForExit();

... но проблема в том, что консоль с ffmpeg появляется и исчезает сразу, поэтому я не могу получить никакой обратной связи. Я даже не знаю, правильно ли выполнялся процесс.

Итак, как я могу:

  • Сообщите, чтобы консоль оставалась открытой

  • Извлеките в С#, что консоль отображается

Ответ 1

Что вам нужно сделать, это захватить стандартный поток вывода:

p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.UseShellExecute = false;
// instead of p.WaitForExit(), do
string q = "";
while ( ! p.HasExited ) {
    q += p.StandardOutput.ReadToEnd();
}

Вам также может понадобиться сделать что-то подобное с StandardError. Затем вы можете сделать то, что хотите, с помощью q.

Это немного утомительно, поскольку я обнаружил в один из моих вопросов

Как отметил Джон Скит, не так уж разумно использовать конкатенацию строк, как это; вместо этого вы должны использовать StringBuilder:

p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.UseShellExecute = false;
// instead of p.WaitForExit(), do
StringBuilder q = new StringBuilder();
while ( ! p.HasExited ) {
    q.Append(p.StandardOutput.ReadToEnd());
}
string r = q.ToString();

Ответ 2

Ответ Lucas имеет условие гонки: если процесс завершается быстро, цикл while остается (или никогда не вводится), даже если есть какой-то выход слева, то есть вы можете пропустить некоторые данные. Чтобы этого не произошло, после завершения процесса необходимо выполнить еще один ReadToEnd.

(Обратите внимание, что по сравнению со старой версией моего ответа я больше не вижу необходимости в WaitForExit, когда флаг process.HasExited имеет значение true, поэтому это сводится к:)

using (var process = Process.Start(startInfo))
{
    var standardOutput = new StringBuilder();

    // read chunk-wise while process is running.
    while (!process.HasExited)
    {
        standardOutput.Append(process.StandardOutput.ReadToEnd());
    }

    // make sure not to miss out on any remaindings.
    standardOutput.Append(process.StandardOutput.ReadToEnd());

    // ...
}

Ответ 3

Для более конкретного ответа, напрямую связанного с ffmpeg, передача команды "-report" в ffmpeg заставит его выгрузить журнал в текущий каталог с тем, что было сказано на дисплее процесса.

'- отчет

Удалите полную командную строку и консольный вывод в файл с именем program-YYYYMMDD-HHMMSS.log в текущем каталоге. Этот файл может быть полезно для отчетов об ошибках. Он также подразумевает подробный список.

Примечание: установка переменной среды FFREPORT для любого значения имеет тот же эффект.

Из Документация FFMpeg.

Ответ 4

Я знаю, что этот вопрос старый, но я все равно добавлю его.

Если все, что вы хотите сделать, это отобразить вывод процесса командной строки, и вы создаете процесс из окна консоли, вам нужно только перенаправить стандартный ввод (да, я знаю, что это звучит неправильно, но оно работает).

Итак:

System.Diagnostics.Process p = new System.Diagnostics.Process();
p.StartInfo = new System.Diagnostics.ProcessStartInfo(ffmpegPath, myParams);
p.UseShellExecute = false;
p.RedirectStandardInput = true;
p.Start();
p.WaitForExit();

Было бы прекрасно.