使用Process.Start()启动进程时出现问题 – 如何构造参数列表?

我有这个:

string cmd = " -i """ + finPath + """ -ar 44100 -ab 160k """ + foutPath + """"; 

我需要使用Systems.Diagnostics.Process将它传递给C#的命令提示符。

没有任何组合似乎有效。 如果我在命令提示符下运行它,程序工作正常。 如果我在VB.Net中使用相同的字符串,也运行得很好

finPathfinPath有空格,它使程序无法运行。

我需要将finPath表示为finPath 。 与foutPath相同。


更多代码(使用此处建议的行,没有运气):

 string inputPath = RootPath + "videoinput\\"; string ffmpegpath = RootPath + "ffmpeg.exe"; //ffmpeg path string outputPath = RootPath +"videooutput\\"; //define new extension string fileext = ".flv"; string newfilename = namenoextension + fileext; string namenoextension = Path.GetFileNameWithoutExtension(savedfile); string fileoutPath = outputPath + newfilename; string fileinPath = "/videoinput/" + savedfile; string cmd = " -i \"" + fileinPath + "\" -ar 44100 -ab 160k \"" + fileoutPath + "\""; //Begin encoding process Process proc = new Process(); proc.StartInfo.FileName = ffmpegpath; proc.StartInfo.Arguments = cmd; proc.StartInfo.UseShellExecute = true; proc.StartInfo.CreateNoWindow = false; proc.StartInfo.RedirectStandardOutput = false; proc.Start(); 

这应该适合你:

 string arguments = string.Format("-i \"{0}\" -ar 44100 -ab 160k \"{1}\"", finPath, foutPath); Process.Start(thePathToExecutable, arguments); 

确保指定与命令行参数分开的可执行文件路径。


编辑以回复评论和问题编辑:

我只是在控制台中运行它,使用以下代码:

 using System; using System.IO; class Program { static void Main(string[] args) { string RootPath = "C:\\"; string savedFile = "test.avi"; string inputPath = Path.Combine(RootPath, "videoinput"); string ffmpegpath = Path.Combine(RootPath, "ffmpeg.exe"); //ffmpeg path string outputPath = Path.Combine(RootPath, "videooutput"); //define new extension string fileext = ".flv"; string namenoextension = Path.GetFileNameWithoutExtension(savedFile); string newfilename = namenoextension + fileext; string fileoutPath = Path.Combine(outputPath, newfilename); string fileinPath = Path.Combine(inputPath, savedFile); string arguments = string.Format("-i \"{0}\" -ar 44100 -ab 160k \"{1}\"", fileinPath, fileoutPath); Console.WriteLine(ffmpegpath); Console.WriteLine(arguments); Console.ReadKey(); } } 

这写出:

 C:\ffmpeg.exe -i "C:\videoinput\test.avi" -ar 44100 -ab 160k "C:\videooutput\test.flv" 

正如我所说 – 如果你这样做,它应该工作。 话虽这么说,我建议您阅读System.IO.Path类,并使用Path.Combine(),Path.GetFullPath()等来修复输入文件。 这也可以帮助您纠正部分问题。

CommandLineToArgvW的文档描述了如何解析参数。 解释这个:

  1. 任何包含空格的参数都应该用外引号括起来。
  2. 参数中的任何内引号都应以反斜杠开头。
  3. 引号前面的反斜杠(或反斜杠序列)应加倍。

可以使用以下类来实现这些结果:

 ///  /// Provides helper functionality for working with Windows process command-lines. ///  public static class WindowsCommandLineHelper { ///  /// Performs escaping and quoting of arguments where necessary to /// build up a command-line suitable for use with the ///  method. ///  /// The arguments to be included on the command-line. /// The resulting command-line. public static string FormatCommandLine(params string[] arguments) { return string.Join(" ", arguments.Select(GetQuotedArgument)); } private static string GetQuotedArgument(string argument) { // The argument is processed in reverse character order. // Any quotes (except the outer quotes) are escaped with backslash. // Any sequences of backslashes preceding a quote (including outer quotes) are doubled in length. var resultBuilder = new StringBuilder(); var outerQuotesRequired = HasWhitespace(argument); var precedingQuote = false; if (outerQuotesRequired) { resultBuilder.Append('"'); precedingQuote = true; } for (var index = argument.Length - 1; index >= 0; index--) { var @char = argument[index]; resultBuilder.Append(@char); if (@char == '"') { precedingQuote = true; resultBuilder.Append('\\'); } else if (@char == '\\' && precedingQuote) { resultBuilder.Append('\\'); } else { precedingQuote = false; } } if (outerQuotesRequired) { resultBuilder.Append('"'); } return Reverse(resultBuilder.ToString()); } private static bool HasWhitespace(string text) { return text.Any(char.IsWhiteSpace); } private static string Reverse(string text) { return new string(text.Reverse().ToArray()); } } 

对于此问题中描述的命令行,您可以这样调用它:

 string commandLine = WindowsCommandLineHelper.FormatCommandLine( "-i", finPath, "-ar", "44100", "-ab", "160k", foutPath); Process.Start(exePath, commandLine); 

UPDATE

这篇博客文章中有更多有趣的信息,以及这里的C#实现 。

这只是逃避报价的问题吗? 您发布的代码使用“”代替\“。对于C#,它应该是:

 string cmd = " -i \"" + finPath + "\" -ar 44100 -ab 160k \"" + foutPath + "\""; 

这是我的尝试:

  public static string QuoteArgument(string arg) { // The inverse of http://msdn.microsoft.com/en-us/library/system.environment.getcommandlineargs.aspx // Suppose we wish to get after unquoting: \\share\"some folder"\ // We should provide: "\\share\\\"some folder\"\\" // Escape quotes ==> \\share\\\"some folder\"\ // For quotes with N preceding backslashes, replace with 2k+1 preceding backslashes. var res = new StringBuilder(); // For sequences of backslashes before quotes: // odd ==> 2x+1, even => 2x ==> "\\share\\\"some folder" var numBackslashes = 0; for (var i = 0; i < arg.Length; ++i) { if(arg[i] == '"') { res.Append('\\', 2 * numBackslashes + 1); res.Append('"'); numBackslashes = 0; } else if(arg[i] == '\\') { numBackslashes++; } else { res.Append('\\', numBackslashes); res.Append(arg[i]); numBackslashes = 0; } } res.Append('\\', numBackslashes); // Enquote, doubling last sequence of backslashes ==> "\\share\\\"some folder\"\\" var numTrailingBackslashes = 0; for (var i = res.Length - 1; i > 0; --i) { if (res[i] != '\\') { numTrailingBackslashes = res.Length - 1 - i; break; } } res.Append('\\', numTrailingBackslashes); return '"' + res.ToString() + '"'; }