I'm trying to run npm
through ProcessBuilder.start()
. However, in Windows at least, whenever I try to start the process without stating the full path of the executable, the invocation fails with "CreateProcess error=2".
EDIT: the directory of npm
is in the PATH environment variable.
Sample code:
public class Main {
public static void main(String[] args) {
// Won't work
invokeCommand(new String[] {"npm", "--version"});
// Will work
invokeCommand(new String[] {"C:\\Program Files\\nodejs\\npm.cmd", "--version"});
}
private static void invokeCommand(String[] args) {
System.out.println("INVOKING: " + String.join(" ", args));
ProcessBuilder pb = new ProcessBuilder(args);
try {
Process p = pb.start();
p.waitFor();
dumpStdout(p);
} catch (IOException e) {
System.out.println(e.getMessage());
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println();
}
private static void dumpStdout(Process p) throws IOException {
String line;
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
while ((line = reader.readLine()) != null) {
System.out.println("STDOUT: " + line);
}
reader.close();
}
}
Why is it so? Is it because npm
is a batch command? That's very inconvenient, not to say inconsistent with other programs like java
or node
that will run just fine without their full paths. Thank you.
Java does scan the Path
for executables, but does not reference the PATHEXT
variable. So change your launcher with the file extension of the executable - which is why it works with appending ".cmd".
It would work with the extension {"npm.cmd", "--version"}
, or without the extension if you use a terminal such as {"cmd.exe", "/c", yourcommand}
as CMD scans the file extensions in the environment variable PATHEXT
. Typically set to:
PATHEXT=.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC