Java Runtime exec() не удается правильно выполнить символы
Об этом уже можно было ответить до этого, но это касалось 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
Ответы
Ответ 1
Вы вызываете программу и ее аргументы за один проход, что эффективно перетаскивает всю строку в среду обработки (надеясь на лучшее).
В системах 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" ), или что разбор парализованного аргумента Windows сначала будет разбираться в пробеле ( что приводит к таким параметрам, как ( "Тест" ). Не имеет смысла, поэтому доступно более одного метода exec
.
Ответ 2
Использование Runtime.exec(String)
- неправильный метод для этого случая (и, как правило, неправильный метод для передачи аргументов новому процессу).
Используйте одну из перегрузок exec, которая принимает массив аргументов для перехода к новому процессу. (Или, см. Ответ Пола в ProcessBuilder - ни один из этих подходов не страдает от проблем с экранированием).
Пример:
exec(new String[] { "vbomanager",
"setextradata", "Test Machine",
"VBoxInternal/Devices/pcnet/0/LUN#0/Config/ssh/HostPort", "2222"});
Счастливое кодирование.
Ответ 3
Вместо того, чтобы процитировать командную строку, вам может быть лучше использовать ProcessBuilder.command(arg0, arg1, ...)
Подробнее см. ProcessBuilder.
Ответ 4
В Windows Runtime.exec(String []) также небезопасен. Если массив аргументов содержит пустую строку, пустой аргумент в основном опущен, что может привести к недопустимой командной строке. Кроме того, кавычки в любом из аргументов не имеют префикса обратной косой черты. Кроме того, ProcessBuilder может добавлять кавычки к аргументам без удвоения числа предшествующих обратных косых черт, что дает смешные результаты, если вы проходите путь к папке, такой как c:\program files\включая обратную косую черту.
Документация Microsoft по их токенизатору командной строки доступна здесь:
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