Java Runtime exec () не может корректно экранировать символы - PullRequest
13 голосов
/ 11 мая 2011

Возможно, на этот вопрос уже был дан ответ, но это касалось Unicode, и я не думаю, что это Unicode (это в ASCII, так что ...).

Когда я выполняю это в моем терминале, проблем не возникает

vboxmanage setextradata "Test Machine" "VBoxInternal/Devices/pcnet/0/LUN#0/Config/ssh/HostPort" 2222

Однако, когда я использую следующее в Java

Runtime.getRuntime().exec("vboxmanage setextradata \"Test Machine\" \"VBoxInternal/Devices/pcnet/0/LUN#0/Config/ssh/HostPort\" 2222");

Возвращает ошибку: незарегистрированный vm '"TestMachine"'

То же самое касается параметров с пробелами в них, таких как Test \ Machine, тогда он не выходит за пределы пробела.

Теперь я думаю, что это как-то связано с кодировкой символов, но я не вижу никакой возможности установить это значение o_O

Ответы [ 4 ]

15 голосов
/ 12 мая 2011

Вы вызываете программу и ее аргументы за один проход, что эффективно помещает всю строку в среду обработки (в надежде на лучшее).

В системах Windows операционная система требует обработкиисполняемый файл и аргументы по-разному, и размещение их всех в одной строке просто требует от вас выбора идеальной строки, которую среда (из которых есть две, о которых я знаю) может быть повторно проанализирована в список аргументов.Лучшее решение состоит в том, чтобы использовать

Runtime.exec(new String[] {"vboxmanage", "setextradata", "Test Machine", "VBoxInternal/Devices/pcnet/0/LUN#0/Config/ssh/HostPort", "2222"});

, что соответствует Runtime's

public Process exec(String[] cmdarray)
         throws IOException

В лучшем случае, с помощью метода одной строки вы в конечном итоге узнаете, как намекнуть и выйтиаргументы, чтобы они не рассматривались как часть имени исполняемого файла, но тогда вы столкнетесь с новой проблемой: они передаются всем как один параметр в исполняемый файл.Как только вы исправите это в зависимости от окружения, вы либо обнаружите, что ваши кавычки не удаляются из параметров (что приводит к таким параметрам, как «2222»), либо синтаксический анализ аргументов в Window собирается сначала проанализировать пробельные символы (приводит к таким параметрам, как («Тест»). Это не имеет смысла, поэтому доступно более одного exec метода.

6 голосов
/ 12 мая 2011

Вместо того, чтобы пытаться заключить в кавычки командную строку, вам лучше использовать ProcessBuilder.command(arg0, arg1, ...)

Подробнее см. ProcessBuilder .

6 голосов
/ 12 мая 2011

Использование Runtime.exec(String) - неправильный метод для этого случая (и вообще неправильный метод для передачи аргументов новому процессу).

Используйте одну из перегрузок exec , которая принимает массив аргументов для передачи новому процессу. (Или посмотрите ответ Пола с ProcessBuilder - ни один из этих подходов не страдает от проблем).

Пример:

exec(new String[] { "vbomanager",
  "setextradata", "Test Machine",
  "VBoxInternal/Devices/pcnet/0/LUN#0/Config/ssh/HostPort", "2222"});

Удачного кодирования.

5 голосов
/ 04 декабря 2011

В Windows Runtime.exec (String []) также небезопасен.Если массив аргументов содержит пустую строку, пустой аргумент в основном опускается, что может привести к неверной командной строке.Кроме того, кавычки в любом из аргументов не начинаются с обратной косой черты.Кроме того, ProcessBuilder может добавлять к аргументам кавычки, не удваивая количество предшествующих обратных слешей, что дает забавные результаты, если передать путь к папке, например c: \ program files \, включая завершающий обратный слеш.токенайзер командной строки доступен здесь: http://msdn.microsoft.com/en-us/library/a1y7w461.aspx

Описанные мной проблемы описаны здесь: http://bugs.sun.com/view_bug.do?bug_id=6468220 и http://bugs.sun.com/view_bug.do?bug_id=6518827

...