Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I launch a subprocess in C# with an argv? (Or convert agrv to a legal arg string)

I have a C# command-line application that I need to run in windows and under mono in unix. At some point I want to launch a subprocess given a set of arbitrary paramaters passed in via the command line. For instance:

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

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

./my_commandline myarg1 myarg2 -- grep "a b c" foo.txt

In this case argv looks like :

argv = {"my_commandline", "myarg1", "myarg2", "--", "grep", "a b c", "foo.txt"}

Note that the quotes around "a b c" are stripped by the shell so if I simply concatenate the arguments in order to create the arg string for ProcessStartInfo I get:

args = "my_commandline myarg1 myarg2 -- grep a b c foo.txt"

Which is not what I want.

Is there a simple way to either pass an argv to subprocess launch under C# OR to convert an arbitrary argv into a string which is legal for windows and linux shell?

Any help would be greatly appreciated.

like image 908
lucas Avatar asked Jun 02 '10 17:06

lucas


People also ask

How does Popen work in C?

The popen() function executes the command specified by the string command. It creates a pipe between the calling program and the executed command, and returns a pointer to a stream that can be used to either read from or write to the pipe.

How do you run a PIPE in subprocess?

To use a pipe with the subprocess module, you have to pass shell=True . In your particular case, however, the simple solution is to call subprocess. check_output(('ps', '-A')) and then str. find on the output.


3 Answers

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

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

like image 106
Daniel Pryden Avatar answered Sep 23 '22 13:09

Daniel Pryden


In windowsland, it's simple really...add extra quotation marks in the string you pass to the System.Diagnostics.ProcessStartInfo object.

e.g. "./my_commandline" "myarg1 myarg2 -- grep \"a b c\" foo.txt"

like image 23
David B Heise Avatar answered Sep 21 '22 13:09

David B Heise


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

/**
 * Let's 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've only tested this on linux. For windows you can just concatenate the args.

like image 34
lucas Avatar answered Sep 21 '22 13:09

lucas