аргументы process.start()

когда я делаю следующую команду в dos, она будет работать нормально

ffmpeg -f image2 -i frame%d.jpg -vcodec mpeg4 -b 800k video.avi

Когда я пытаюсь использовать класс процесса в С# без аргументов, он загружает ffmpeg в окно консоли, а затем исчезает, как обычно. Однако, когда я пытаюсь использовать аргумент, как я делал выше, отформатированный точно так же... он не работает! ffmpeg все еще загружается, однако, поскольку окно консоли закрывается так быстро, я не могу определить, в чем ошибка:/

Process ffmpeg = new Process();
ffmpeg.StartInfo.FileName = path + "//" + "ffmpeg.exe";
ffmpeg.StartInfo.Arguments = " -f image2 -i frame%d.jpg -vcodec mpeg4 -b 800k video.avi";
ffmpeg.Start();

Кто-нибудь знает, почему это так? Почему команда работает из-под DOS, а затем не работает в C#, даже если аргументы точно такие же? Я использовал этот метод раньше для многих вещей и никогда не сталкивался с этим.


person brux    schedule 16.07.2010    source источник
comment
Вы уверены, что FileName правильный? Разве косая черта не должна быть \\, а не //.   -  person Jason Evans    schedule 16.07.2010
comment
Вместо этого используйте System.IO.Path.Combine(path, ffmpeg.exe). Это помещает правильный разделитель каталогов в путь, если его еще нет.   -  person Tergiver    schedule 16.07.2010
comment
да, свойство имени файла правильное, как я уже сказал, приятель, процесс фактически начинается, поэтому файл должен быть найден, его аргументы не работают. Я попытался объединить строку, а затем передать ее аргументам вместо приведенных выше, но все равно без радости: ‹   -  person brux    schedule 16.07.2010
comment
если мне нужно преобразовать .caf в .mp3, какие должны быть аргументы процесса   -  person    schedule 17.04.2014


Ответы (5)


Попробуйте полностью определить имена файлов в аргументах — я заметил, что вы указываете путь в части FileName, поэтому возможно, что процесс запускается в другом месте, а затем не находит аргументы и вызывает ошибку.

Если это сработает, установите свойство WorkingDirectory. в StartInfo может пригодиться.

Собственно, по ссылке

Свойство WorkingDirectory должно быть установлено, если указаны имя пользователя и пароль. Если свойство не задано, рабочим каталогом по умолчанию является %SYSTEMROOT%\system32.

person cristobalito    schedule 16.07.2010
comment
спасибо, я установил для свойства workdirectory тот же путь, что и для ffmpeg, и теперь он работает - person brux; 17.07.2010
comment
/k \c:\\users\\jafar.baltidynamolog\\documents\\visual studio 2010\\Projects\\VideoProjectBilal\\VideoProjectBilal\\bin\\Debug\\ffmpeg.exe\ -i \C:\\Users \\jafar.baltidynamolog\\Видео\\видео\\SampleVideo_360x240_2mb.mp4\ -i \C:\\Пользователи\\jafar.baltidynamolog\\Видео\\изображения\\2.png\ -filter_complex \overlay=10:10 \\c:\\users\\jafar.baltidynamolog\\documents\\visual studio 2010\\Projects\\VideoProjectBilal\\VideoProjectBilal\\bin\\Debug\\Output\\SampleVideo_360x240_2mb_Output.mp4\ Сначала возникает проблема космос. Пожалуйста, помогите - person Charlie; 30.11.2015
comment
Так какой ответ? - person Demodave; 01.01.2019

Не совсем прямой ответ, но я настоятельно рекомендую использовать LINQPad для такого рода "исследовательского" программирования на C#.

У меня есть сохраненный «запрос» в LINQPad:

var p = new System.Diagnostics.Process();
p.StartInfo.FileName = "cmd.exe";
p.StartInfo.Arguments = "/c echo Foo && echo Bar";
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.UseShellExecute = false;
p.StartInfo.CreateNoWindow = true;
p.Start();
p.StandardOutput.ReadToEnd().Dump();

Не стесняйтесь адаптироваться по мере необходимости.

person Daniel Pryden    schedule 16.07.2010
comment
не забудьте добавить p.StandardError.ReadToEnd().Dump(); для тех (редких) приложений, которые также пишут в stderr. - person Tergiver; 17.07.2010
comment
@Tergiver: За исключением того, что из-за бафтинга вызов ReadToEnd в одном потоке перед другим может привести к взаимоблокировке. Конечно, это вряд ли будет проблемой для большинства программ, но я решил, что, например, в коде лучше что-то упустить, чем реализовать это неправильно. - person Daniel Pryden; 17.07.2010
comment
Я никогда не пробовал так, я асинхронно читал оба потока при перенаправлении процесса. Я понимаю, почему вы привели этот простой пример вместо полного (асинхронного). - person Tergiver; 17.07.2010

Обязательно используйте полные пути, например. не только "video.avi", но и полный путь к этому файлу.

Простым трюком для отладки будет запуск командного окна с использованием cmd /k <command>вместо этого:

string ffmpegPath = Path.Combine(path, "ffmpeg.exe");
string ffmpegParams = @"-f image2 -i frame%d.jpg -vcodec"
    + @" mpeg4 -b 800k C:\myFolder\video.avi"

Process ffmpeg = new Process();
ffmpeg.StartInfo.FileName = "cmd.exe";
ffmpeg.StartInfo.Arguments = "/k " + ffmpegPath + " " + ffmpegParams
ffmpeg.Start();

Это оставит командное окно открытым, чтобы вы могли легко проверить вывод.

person Dirk Vollmar    schedule 16.07.2010
comment
@ 0xA3 Это действительно работает. ffmpeg исчезает слишком быстро, чтобы сделать снимок, даже если я использую process.WaitForExit(10 * 1000)10(s). Что на самом деле означает этот /k? Как нашел? Спасибо. - person Alston; 14.06.2013
comment
@Stallman: /k означает, что командное окно не закрывается, а остается открытым. Вы можете получить все параметры, вызвав cmd.exe /? в командной строке. - person Dirk Vollmar; 14.06.2013

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

Погляди:

Если вы установите для каждого из них значение true, то позже вы сможете вызвать process.StandardOutput.ReadToEnd() и process.StandardError.ReadToEnd(), чтобы получить выходные данные в строковых переменных, которые вы можете легко проверить в отладчике, или вывести в трассировку или в файл журнала.

person Chris W. Rea    schedule 16.07.2010

Крайний случай, но мне пришлось использовать программу, которая работала правильно только тогда, когда я указал

StartInfo = {..., RedirectStandardOutput = true}

Не указание его приведет к ошибке. После этого даже не было необходимости читать вывод.

person Bene Tleilax    schedule 04.06.2018