Как запустить подпроцесс в C # с argv? (Или преобразовать agrv в допустимую строку arg) - PullRequest
7 голосов
/ 02 июня 2010

У меня есть приложение командной строки C #, которое мне нужно запустить в Windows и под моно в Unix. В какой-то момент я хочу запустить подпроцесс с заданным набором произвольных параметров, передаваемых через командную строку. Например:

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

К сожалению, System.Diagnostics.ProcessStartInfo принимает строку только для аргументов. Это проблема для таких команд, как:

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

В этом случае argv выглядит так:

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

Обратите внимание, что кавычки вокруг "a b c" удаляются оболочкой, поэтому, если я просто объединю аргументы для создания строки аргумента для ProcessStartInfo, я получу:

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

Чего я не хочу.

Есть ли простой способ передать argv в запуск подпроцесса под C # ИЛИ преобразовать произвольный argv в строку, которая допустима для Windows и оболочки Linux?

Любая помощь будет принята с благодарностью.

Ответы [ 5 ]

1 голос
/ 03 июня 2010

Спасибо всем за предложения. Я закончил тем, что использовал алгоритм из 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;
}

Я проверял это только на Linux. Для окон вы можете просто объединить аргументы.

1 голос
/ 03 июня 2010

В Windowsland это действительно просто ... добавить дополнительные кавычки в строку, которую вы передаете объекту System.Diagnostics.ProcessStartInfo.

например. "./my_commandline" "myarg1 myarg2 - grep \" a b c \ "foo.txt"

1 голос
/ 02 июня 2010

MSDN содержит описание , как среда выполнения MS Visual C анализирует строку , возвращаемую GetCommandLine(), в массив argv.

Вас также может заинтересовать функция list2cmdline() из стандартной библиотеки Python, которая используется модулем Python subprocess для эмуляции поведения Unix argv в среде Win32.

0 голосов
/ 03 июня 2010

Просто используйте регулярное выражение, чтобы проверить, есть ли в строке пробелы любого типа, и замените исходную строку новой строкой в ​​кавычках:

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 голосов
/ 02 июня 2010

Вам потребуется запустить новый подпроцесс, используя grep и все аргументы, которые понадобятся grep.

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
    }
}

затем позвоните на runProcess("grep", "a", "b", "c", "foo.txt");

Редактировать: Обновлена ​​обработка аргументов.

...