How to start a subprocess in C # using argv? (Or convert agrv to legal arg string)

I have a C # command line application that I need to run on windows and under mono on unix. At some point, I want to start a subprocess, given the set of arbitrary parameters that passed through the command line. For example:

Usage: mycommandline [-args] -- [arbitrary program] 

Unfortunately, System.Diagnostics.ProcessStartInfo accepts only a string for arguments. This is a problem for commands such as:

 ./my_commandline myarg1 myarg2 -- grep "abc" foo.txt 

In this case, argv looks like this:

 argv = {"my_commandline", "myarg1", "myarg2", "--", "grep", "abc", "foo.txt"} 

Note that the quotation marks around "abc" are separated by the shell, so if I just concatenate the arguments to create an arg string for ProcessStartInfo, I get:

 args = "my_commandline myarg1 myarg2 -- grep abc foo.txt" 

This is not what I want.

Is there an easy way to either pass argv to run the subprocess in C # OR, or convert an arbitrary argv to a string that is legal for windows and the Linux shell?

Any help would be greatly appreciated.

+7
c # shell subprocess mono argv
source share
5 answers

Thanks everyone for the suggestions. I ended up using the algorithm from shquote ( http://www.daemon-systems.org/man/shquote.3.html ).

 /** * Let assume 'command' contains a collection of strings each of which is an * argument to our subprocess (it does not include arg0). */ string args = ""; string curArg; foreach (String s in command) { curArg = s.Replace("'", "'\\''"); // 1.) Replace ' with '\'' curArg = "'"+curArg+"'"; // 2.) Surround with 's // 3.) Is removal of unnecessary ' pairs. This is non-trivial and unecessary args += " " + curArg; } 

I tested this only on linux. For windows, you can simply concatenate the arguments.

+1
source share

MSDN has a description of how MS Visual C Runtime parses the string returned by GetCommandLine() into the argv array.

You might also be interested in the list2cmdline() function from the Python standard library, which is used by the Python subprocess module to emulate the behavior of Unix argv in a Win32 environment.

+1
source share

In windowsland, it's just ... add extra quotes to the string you pass to the System.Diagnostics.ProcessStartInfo object.

eg. "./my_commandline" "myarg1 myarg2 - grep \" abc \ "foo.txt"

+1
source share

You will need to start a new subprocess using grep , and all the arguments grep will need.

 void runProcess(string processName, string args) { using (Process p = new Process()) { ProcessStartInfo info = new ProcessStartInfo(processName); info.Arguments = args; info.RedirectStandardInput = true; info.RedirectStandardOutput = true; info.UseShellExecute = false; p.StartInfo = info; p.Start(); string output = p.StandardOutput.ReadToEnd(); // process output } } 

then call runProcess("grep", "a", "b", "c", "foo.txt");

Edit: Updated processing of arguments.

0
source share

Just use Regex to check if the string has spaces of any type, and replace the original string with a new one with quotes:

 using System.Text.RegularExpressions; // ... for(int i=0; i<argv.Length; i++) { if (Regex.IsMatch(i, "(\s|\")+")) { argv[i] = "\"" + argv[i] + "\""; argv[i].Replace("\"", "\\\""); } } 
0
source share

All Articles