Как запустить подпроцесс в 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("\"", "\\"");
}
}