views:

652

answers:

3

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.

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

finPath has spaces as does foutPath and it's making the program not run.

I need to have finPath expressed as "finPath". Same with 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();

+7  A: 

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.

Reed Copsey
comes out as:"-i \"videoinput/file.wmv\" -ar 44100 -ab 160k \"C:\\Documents and Settings\\user\\My Documents\\Visual Studio 2008\\Projects\\projectname\\videooutput/eaf2cc1d-6mtnR.flv\"" the \ after -i and the \ after 160k is still a problem when you run in command prompt, although there is now a quotation mark around the filenames.
@Haste: I just edited to show you how to make this work. I put an entire program in the source - and tested it. This definitely works.
Reed Copsey
@Haste: Try using the code I put in my edit, instead of trying to use + to concatenate your strings. I tested it, and it works, with no extra stuff (as you can see in my reply). The switch to using String.Format is much easier to read, and less problematic.
Reed Copsey
Works. Thank you so very much.Just had to make a few changes for design and database reasons.Thanks.
Figured I should add that I didn't think it was working because the debugger was still showing the backslashes, but then I let it run through the breakpoints and it worked.
+2  A: 

Is this just a problem escaping the quotes? The code you posted uses "" instead of \". For C# it should be:

string cmd = " -i \"" + finPath + "\" -ar 44100 -ab 160k \"" + foutPath + "\"";
Jon B
No, the problem is adding quotes around finPath and foutPath.
@Haste: this will add quotes around those two variables. Your code was using "" instead of \", which is what you need in C#.
Jon B
A: 

Here's part of a class I wrote a while back to deal with passing arguments to commandlines in Windows. Any argument that contains whitespace gets quotes around it and any quotes embedded within it get escaped by preceding them with backslashes. There is some extra escaping to be done with backslashes that precede an embedded quote (there is a little bit of information in the documentation for CommandLineToArgvW).

/// <summary>
/// Provides shared helper functionality for working with Windows process command-lines.
/// </summary>
internal 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="Process.Start" /> 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)
    {
        arguments = (string[])arguments.Clone();
        for (int index = 0; index < arguments.Length; index++)
        {
            arguments[index] = GetQuotedArgument(arguments[index]);
        }
        return string.Join(" ", arguments);
    }

    private static string GetQuotedArgument(string argument)
    {
        // The method reads the input argument backwards and builds
        // the result in reverse-character order.
        StringBuilder resultBuilder = new StringBuilder();

        // If the text has whitespace, it must be surrounded in quotes.
        bool surroundingQuotesRequired = HasWhitespace(argument);

        // This flag tracks whether the last character processed was a
        // quote or a backslash that belongs to a sequence of backslashes
        // that immediately precede a quote.
        bool precedingQuote = false;

        // If surrounding quotes are required, start with one.
        // This means that any slashes at the end must be doubled up,
        // so we must also set the precedingQuote flag.
        if (surroundingQuotesRequired)
        {
            resultBuilder.Append('"');
            precedingQuote = true;
        }

        // Read the argument string backwards, escaping any quotes and backslashes
        // where necessary (backslashes are OK unless in a sequence preceding a quote).
        for (int index = argument.Length - 1; index >= 0; index--)
        {
            char character = argument[index];
            resultBuilder.Append(character);

            if (character == '"')
            {
                precedingQuote = true;
                resultBuilder.Append('\\');
            }
            else if (character == '\\' && precedingQuote)
            {
                resultBuilder.Append('\\');
            }
            else
            {
                precedingQuote = false;
            }
        }

        // If surrounding quotes are required, add one.
        if (surroundingQuotesRequired)
        {
            resultBuilder.Append('"');
        }

        // Reverse the result and we're done.
        return Reverse(resultBuilder.ToString());
    }

    private static bool HasWhitespace(string argument)
    {
        // Iterate over the string and return true if it contains any whitespace characters.
        foreach (char character in argument)
        {
            if (char.IsWhiteSpace(character))
            {
                return true;
            }
        }
        return false;
    }

    private static string Reverse(string input)
    {
        // Convert the string to a character array, reverse the order
        // and convert it back.
        char[] array = input.ToCharArray();
        Array.Reverse(array);
        return new string(array);
    }
}

You'd call it like this:

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

There is a little bit of information in the documentation for CommandLineToArgvW.

Dave Cluderay