I've got this:
我有这个:
string cmd = " -i """ + finPath + """ -ar 44100 -ab 160k """ + foutPath + """";
and I need to pass it to command prompt from C# using Systems.Diagnostics.Process
.
我需要使用Systems.Diagnostics.Process将它传递给C#的命令提示符。
No combination seems to work. Program works just fine if I run it in command prompt. Also runs just fine if I use the same string in VB.Net
没有任何组合似乎有效。如果我在命令提示符下运行它,程序工作正常。如果我在VB.Net中使用相同的字符串,也运行得很好
finPath
has spaces as does foutPath
and it's making the program not run.
finPath和foutPath一样有空格,它使程序无法运行。
I need to have finPath
expressed as finPath
. Same with foutPath
.
我需要将finPath表示为finPath。与foutPath相同。
More of the code (used the line suggested here, no luck):
更多代码(使用此处建议的行,没有运气):
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 个解决方案
#1
This should work for you:
这应该适合你:
string arguments = string.Format("-i \"{0}\" -ar 44100 -ab 160k \"{1}\"", finPath, foutPath);
Process.Start(thePathToExecutable, arguments);
Make sure to specify the executable's path separate from the command line arguments.
确保指定与命令行参数分开的可执行文件路径。
Edit in response to comments and question edit:
编辑以回复评论和问题编辑:
I just ran this in a console, using the following code:
我只是在控制台中运行它,使用以下代码:
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();
}
}
This writes out:
这写出:
C:\ffmpeg.exe
-i "C:\videoinput\test.avi" -ar 44100 -ab 160k "C:\videooutput\test.flv"
As I said - if you do it this way, it should work. That being said, I'd recommend reading up on the System.IO.Path class, and use Path.Combine(), Path.GetFullPath(), etc, to fix your input files. This may help you correct part of your issue, as well.
正如我所说 - 如果你这样做,它应该工作。话虽这么说,我建议您阅读System.IO.Path类,并使用Path.Combine(),Path.GetFullPath()等来修复输入文件。这也可以帮助您纠正部分问题。
#2
The documentation for CommandLineToArgvW describes how the arguments are parsed. Interpreting this:
CommandLineToArgvW的文档描述了如何解析参数。解释这个:
- Any argument that contains whitespace should be surrounded in outer quotes.
- Any inner quotes in the argument should be preceded by backslashes.
- Backslashes (or sequences of backslashes) that precede a quote should be doubled up.
任何包含空格的参数都应该用外引号括起来。
参数中的任何内引号都应以反斜杠开头。
引号前面的反斜杠(或反斜杠序列)应加倍。
The following class can be used to achieve these results:
可以使用以下类来实现这些结果:
/// <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());
}
}
For the command line described in this question, you'd call it like this:
对于此问题中描述的命令行,您可以这样调用它:
string commandLine = WindowsCommandLineHelper.FormatCommandLine(
"-i", finPath, "-ar", "44100", "-ab", "160k", foutPath);
Process.Start(exePath, commandLine);
UPDATE
There is more interesting information along these lines in this blog post, and a C# implementation here.
这篇博客文章中有更多有趣的信息,以及这里的C#实现。
#3
Is this just a problem escaping the quotes? The code you posted uses "" instead of \". For C# it should be:
这只是逃避报价的问题吗?您发布的代码使用“”代替\“。对于C#,它应该是:
string cmd = " -i \"" + finPath + "\" -ar 44100 -ab 160k \"" + foutPath + "\"";
#4
And here's my attempt:
这是我的尝试:
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() + '"';
}
#1
This should work for you:
这应该适合你:
string arguments = string.Format("-i \"{0}\" -ar 44100 -ab 160k \"{1}\"", finPath, foutPath);
Process.Start(thePathToExecutable, arguments);
Make sure to specify the executable's path separate from the command line arguments.
确保指定与命令行参数分开的可执行文件路径。
Edit in response to comments and question edit:
编辑以回复评论和问题编辑:
I just ran this in a console, using the following code:
我只是在控制台中运行它,使用以下代码:
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();
}
}
This writes out:
这写出:
C:\ffmpeg.exe
-i "C:\videoinput\test.avi" -ar 44100 -ab 160k "C:\videooutput\test.flv"
As I said - if you do it this way, it should work. That being said, I'd recommend reading up on the System.IO.Path class, and use Path.Combine(), Path.GetFullPath(), etc, to fix your input files. This may help you correct part of your issue, as well.
正如我所说 - 如果你这样做,它应该工作。话虽这么说,我建议您阅读System.IO.Path类,并使用Path.Combine(),Path.GetFullPath()等来修复输入文件。这也可以帮助您纠正部分问题。
#2
The documentation for CommandLineToArgvW describes how the arguments are parsed. Interpreting this:
CommandLineToArgvW的文档描述了如何解析参数。解释这个:
- Any argument that contains whitespace should be surrounded in outer quotes.
- Any inner quotes in the argument should be preceded by backslashes.
- Backslashes (or sequences of backslashes) that precede a quote should be doubled up.
任何包含空格的参数都应该用外引号括起来。
参数中的任何内引号都应以反斜杠开头。
引号前面的反斜杠(或反斜杠序列)应加倍。
The following class can be used to achieve these results:
可以使用以下类来实现这些结果:
/// <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());
}
}
For the command line described in this question, you'd call it like this:
对于此问题中描述的命令行,您可以这样调用它:
string commandLine = WindowsCommandLineHelper.FormatCommandLine(
"-i", finPath, "-ar", "44100", "-ab", "160k", foutPath);
Process.Start(exePath, commandLine);
UPDATE
There is more interesting information along these lines in this blog post, and a C# implementation here.
这篇博客文章中有更多有趣的信息,以及这里的C#实现。
#3
Is this just a problem escaping the quotes? The code you posted uses "" instead of \". For C# it should be:
这只是逃避报价的问题吗?您发布的代码使用“”代替\“。对于C#,它应该是:
string cmd = " -i \"" + finPath + "\" -ar 44100 -ab 160k \"" + foutPath + "\"";
#4
And here's my attempt:
这是我的尝试:
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() + '"';
}