Как запустить подпроцесс в C# с помощью argv? (Или преобразовать agrv в юридическую строку arg)

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

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

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

./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 " удаляются оболочкой, поэтому, если я просто объединяю аргументы, чтобы создать строку arg для ProcessStartInfo, я получаю:

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

это не то, что я хочу.

есть ли простой способ передать argv для запуска подпроцесса под C# или преобразовать произвольный argv в строку, которая является законной для Windows и linux shell?

любая помощь была бы весьма признательна.

5 ответов


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

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


в windowsland, это действительно просто...добавьте дополнительные кавычки в строку, передаваемую системе.Диагностика.Изменение панели объекта.

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


спасибо всем за предложения. В итоге я использовал алгоритм из 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. Для windows вы можете просто объединить args.


вам нужно будет запустить новый подпроцесс с помощью 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");

Edit: обновлена обработка args.


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

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