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"); 

它返回一个错误:unregistered vm’“TestMachine”’

其中包含空格的参数(如Test \ Machine)也是如此,然后它不会逃避空间。

现在我认为这与字符编码有关,但我没有看到任何设置o_O的选项

您在一次调用中调用程序及其参数,这有效地将整个字符串推入处理环境(希望最好)。

在Windows系统中,操作系统以不同的方式处理可执行文件和参数,并将它们全部放在同一个字符串中只需要您选择一个完美的字符串,该环境(其中有两个我知道的)可以重新生成-parse到参数列表中。 更好的解决方案是使用

 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 

充其量,使用一个字符串方法,您最终将找到如何提示和转义参数,以便它们不会被视为可执行文件名的一部分,但随后您将遇到一个新问题,它们会被传递all作为可执行文件的一个参数。 一旦你根据环境修复它,你会发现你的引号没有被从参数中剥离(导致像“2222”这样的参数),或者Window的半破坏参数解析将首先解析空白(导致像(“测试”)这样的参数。这没有意义,这就是为什么有多个exec方法可用的原因。

对于这种情况,使用Runtime.exec(String)是错误的方法(通常是将参数传递给新进程的错误方法)。

使用其中一个exec重载 ,它将一组参数传递给新进程。 (或者,请参阅Paul对ProcessBuilder的回答 – 这些方法都不会遇到逃避问题)。

例:

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

快乐的编码。

而不是尝试引用命令行,您可能最好使用ProcessBuilder.command(arg0, arg1, ...)

有关详细信息,请参阅ProcessBuilder 。

在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? bad_id = 6468220和http://bugs.sun.com/view_bug.do?bug_id=6518827