Java ProcessBuilder:找到 .cmd nad .exe 但不是 .bat

mty*_*son 1 java external

正如标题所说,我使用的是基本的 ProcessBuilder:

ProcessBuilder pb = new ProcessBuilder(new String[] {this.getExecutable(), "--version"});
             pb.directory(pomDir);
             pb.redirectOutput(appendTo(log));
             Process p = pb.start();
             p.waitFor();
Run Code Online (Sandbox Code Playgroud)

如果 getExecutable() 是路径上的 .exe(如 Python.exe)或 .cmd(如 npm.cmd),则此方法有效。

但是,如果它是 .bat(如 mvn.bat),则不是。

以下是相关的路径条目:

c:\Python27;
c:\Users\Matt\Tools\apache-maven-3.3.9\bin;
c:\Users\Matt\Tools\node;
Run Code Online (Sandbox Code Playgroud)

python --version 的输出:

Python 2.7.10
Run Code Online (Sandbox Code Playgroud)

mvn --version 的输出:

Exception in thread "main" java.lang.RuntimeException: Error running mvn init
        at tech.project.trait.act(act.java:81)
        at tech.project.admin.action.LastDependendantInvoker.invoke(LastDependendantInvoker.java:23)
        at tech.project.admin.command.NewAppCommand.execute(NewAppCommand.java:71)
        at tech.project.admin.command.init.InitCommand.execute(InitCommand.java:33)
        at tech.project.admin.CLI.main(CLI.java:83)
Caused by: java.io.IOException: Cannot run program "mvn.bat" (in directory "c:\Users\Matt\Documents\Projects\foo"): CreateProcess error=2, The system cannot find the file specified
        at java.lang.ProcessBuilder.start(Unknown Source)
        at tech.project.trait.act(act.java:75)
        ... 4 more
Caused by: java.io.IOException: CreateProcess error=2, The system cannot find the file specified
        at java.lang.ProcessImpl.create(Native Method)
        at java.lang.ProcessImpl.<init>(Unknown Source)
        at java.lang.ProcessImpl.start(Unknown Source)
        ... 6 more
Run Code Online (Sandbox Code Playgroud)

如果我尝试将它包装起来,cmd我会得到:

cmd //C mvn --version
Microsoft Windows [Version 10.0.14393]
(c) 2016 Microsoft Corporation. All rights reserved.
Run Code Online (Sandbox Code Playgroud)

从命令行, mvn --version 返回:

mvn --version
Apache Maven 3.3.9 (bb52d8502b132ec0a5a3f4c09453c07478323dc5; 2015-11-10T10:41:47-06:00)
Maven home: c:\Users\Matt\Tools\apache-maven-3.3.9
Java version: 1.8.0_73, vendor: Oracle Corporation
Java home: c:\Program Files\Java\jdk1.8.0_73\jre
Default locale: en_US, platform encoding: Cp1252
OS name: "windows 10", version: "10.0", arch: "amd64", family: "dos"
Run Code Online (Sandbox Code Playgroud)

想法?


根据@Adroidan 的评论,我尝试过:

"cmd.exe", "//C",  "\""+this.getExecutable()+" --version\""
Run Code Online (Sandbox Code Playgroud)

但这似乎产生了一个新的 cmd shell,并打印了 cmd.exe 版本:

Microsoft Windows [Version 10.0.14393]
(c) 2016 Microsoft Corporation. All rights reserved.
Run Code Online (Sandbox Code Playgroud)

从命令行,等效的工作正常:

$ cmd.exe //C "mvn --version"
Apache Maven 3.3.9 (bb52d8502b132ec0a5a3f4c09453c07478323dc5; 2015-11-10T10:41:47-06:00)
Maven home: C:\Users\Matt\Tools\apache-maven-3.3.9
Java version: 1.8.0_73, vendor: Oracle Corporation
Java home: C:\Program Files\Java\jdk1.8.0_73\jre
Default locale: en_US, platform encoding: Cp1252
OS name: "windows 10", version: "10.0", arch: "amd64", family: "dos"
Run Code Online (Sandbox Code Playgroud)

Boh*_*ian 5

以下是基础知识:

  • 对于 bat 文件,可执行文件应该是 "cmd.exe"
  • 参数是蝙蝠加上它的参数作为单个字符串,例如 "mvn --version"
  • 添加"/C"以便cmd外壳不会继续运行

所以你的代码应该是这样的:

new ProcessBuilder().command("cmd.exe", "/C", "mvn --version")
Run Code Online (Sandbox Code Playgroud)

(尽管您可能需要完全限定通往 的路径mvn


这是一个完整的最小工作示例:

创建一个c:\tools\test.bat包含以下内容的文件:

@echo off
echo I was passed: %1
Run Code Online (Sandbox Code Playgroud)

然后,运行这个:

Process p = new ProcessBuilder().command("cmd.exe", "/C", "/tools/test.bat foo").start();
p.waitFor();
System.out.println(new Scanner(p.getInputStream()).useDelimiter("\\A").next());
Run Code Online (Sandbox Code Playgroud)

产生这个:

I was passed: foo
Run Code Online (Sandbox Code Playgroud)