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

时间:2009-06-04 19:47:02

标签: c# string

我有这个:

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

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

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

,也运行得很好

finPathfoutPath一样有空格,它会使程序无法运行。

我需要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();

4 个答案:

答案 0 :(得分:9)

这应该适合你:

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()等来修复输入文件。这也可以帮助您纠正部分问题。

答案 1 :(得分:3)

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

  1. 任何包含空格的参数都应包含在内 外部报价。
  2. 参数中的任何内部引号都应以。开头 反斜杠。
  3. 前面的反斜杠(或反斜杠序列) 报价应加倍。
  4. 以下类可用于实现这些结果:

    /// <summary>
    /// Provides helper functionality for working with Windows process command-lines.
    /// </summary>
    public static class WindowsCommandLineHelper
    {
        /// <summary>
        /// Performs escaping and quoting of arguments where necessary to
        /// build up a command-line suitable for use with the
        /// <see cref="System.Diagnostics.Process.Start(string,string)" /> method.
        /// </summary>
        /// <param name="arguments">The arguments to be included on the command-line.</param>
        /// <returns>The resulting command-line.</returns>
        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);
    

    <强>更新

    this blog postC# implementation here中,这些行中有更多有趣的信息。

答案 2 :(得分:2)

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

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

答案 3 :(得分:0)

这是我的尝试:

    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() + '"';
    }