1

I have a .NET program that launches cmd.exe to execute another program, "MyProgam.exe". I do this instead of launching MyProgram.exe because I need to run that as Administrator as well as capturing its output.

Here's what I have:

Process process = new Process();
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.FileName = "cmd.exe";
string args =
    @"/C ""C:\Program Files (x86)\MyFolder\MyProgram.exe"" ""arg1"" ""arg2"" > out.txt 2>&1";
startInfo.Arguments = args;
process.StartInfo = startInfo;
process.Start();

However, the output (as captured in output.txt) is:

'C:\Program' is not recognized as an internal or external command, operable program or batch file.

So it appears as though the quotes surrounding C:\Program Files (x86)\MyFolder\MyProgram.exe are ignored. I have tried to wrap it in an extra pair of quotes, like this:

@"/C """"C:\Program Files (x86)\MyFolder\MyProgram.exe"""" ""arg1"" ""arg2"" > out.txt 2>&1";

which then produces the following:

The filename, directory name, or volume label syntax is incorrect.

What am I missing?

Zoomzoom
  • 1,042
  • 2
  • 13
  • 32
  • 1
    Is there a particular reason why you need `cmd` to write output to a file instead of just starting the program and writing its output stream to said file? `cmd` has some peculiarities with quoting (see `cmd /?`) and how command lines are parsed, which then further interacts with how the program you put there gets and parses its arguments ... it's not pretty and I'd avoid it for sanity's sake alone. – Joey Jan 24 '18 at 15:24
  • Have you tried escaping the quotes on the inside? – C.J. Jan 24 '18 at 15:24
  • You need to wrap the *WHOLE* call to /C within quotes as well. See: https://stackoverflow.com/questions/6376113/how-do-i-use-spaces-in-the-command-prompt – aquinas Jan 24 '18 at 15:27
  • Possible duplicate of [How do I use spaces in the Command Prompt?](https://stackoverflow.com/questions/6376113/how-do-i-use-spaces-in-the-command-prompt) – aquinas Jan 24 '18 at 15:27
  • @Joey I'm using redirect to a file because I need to set Verb = "runas" and UseShellExecute = true which disable standard redirect. Sorry didn't include it in the sample code, thought it was redundant detail. – Zoomzoom Jan 24 '18 at 15:28
  • @aquinas I tried wrapping the whole thing in another pair of quotes, still no dice: @"""/C """"C:\Program Files (x86)\MyFolder\MyProgram.exe"""" ""arg1"" ""arg2"""" > out.txt 2>&1"; – Zoomzoom Jan 24 '18 at 15:30
  • 1
    @Zoomzoom, not quite right. Like this: `@"/C """"C:\Program Files (x86)\MyFolder\foo.bat"" ""arg1"" ""arg2"""" > out.txt 2>&1"` – aquinas Jan 24 '18 at 16:49
  • @aquinas that's actually the same as the second attempt in my question details, and it doesn't work either... Thanks though! – Zoomzoom Jan 24 '18 at 18:19
  • 1
    It's not the same: you had: `@"/C """"exe"""" ""arg1"" ""arg2"" > out.txt 2>&1"` and I had `@"/C """"exe"" ""arg1"" ""arg2"""" > out.txt 2>&1"` to make this clearer: what you need is a double quote around the ENTIRE /c argument, not just the executable path. e.g., `cmd /c "whatever.exe /someArgument"` – aquinas Jan 24 '18 at 18:28
  • @aquinas sorry about that, you're right. And I did try that, which is the same as the 2nd suggestion that Racil's answer provides. But it didn't work. For some crazy reason, only parentheses work for me. – Zoomzoom Jan 24 '18 at 18:38

1 Answers1

1

According to CMD documentation:

If you specify /c or /k, cmd processes the remainder of string and quotation marks are preserved only if all of the following conditions are met:

• You do not use /s.

• You use exactly one set of quotation marks.

• You do not use any special characters within the quotation marks (for example: &<>( ) @ ^ |).

• You use one or more white-space characters within the quotation marks.

• The string within quotation marks is the name of an executable file.

If the previous conditions are not met, string is processed by examining the first character to verify whether or not it is an opening quotation mark. If the first character is an opening quotation mark, it is stripped along with the closing quotation mark. Any text following the closing quotation marks is preserved.

So you have to use one single pair of quotes to satisfy the conditions. If your arg1 and arg2 don't have spaces, only use quotes surrounding the path:

@"/C ""C:\Program Files (x86)\MyFolder\MyProgram.exe"" arg1 arg2 > out.txt 2>&1"

If your two arguments have spaces, you'll fall into the last paragraph (because you'll need to use more than one pair of quotes). You have to add quotes around each argument and also enclose theme altogether in an additional pair of quotes:

@"/C """"C:\Program Files (x86)\MyFolder\MyProgram.exe"" ""arg1"" ""arg2"""" > out.txt 2>&1"

Alternatively, enclose the arguments in parentheses which is valid batch and makes it a bit easier to read:

@"/C (""C:\Program Files (x86)\MyFolder\MyProgram.exe"" ""arg1"" ""arg2"") > out.txt 2>&1"
Racil Hilan
  • 24,690
  • 13
  • 50
  • 55
  • Thanks, I had to use parentheses (your 3rd sample) for it to work. Your 2nd sample is something I already tried, as mentioned in my question, and it didn't work for me although it returned a slightly different message. – Zoomzoom Jan 24 '18 at 18:22
  • Hmmm, that's strange! I tried the three options and they all worked. Anyway, I'm glad the parentheses option worked for you, they are a little easier to read too. – Racil Hilan Jan 24 '18 at 21:04