Background
By using the .bat
file from here, you can run a PowerShell script by just click the .bat
file.
Problem
When you are trying to run the .bat
file from Java ProcessBuilder
class like this, the .bat
file will never finish and ProcessBuilder
will freeze.
package org.example; import java.io.IOException; import java.util.ArrayList; import java.util.List; public class Main { public static void main(String[] args) throws IOException, InterruptedException { List<String> list = new ArrayList<String>(); list.add("c:/tmp/hoge.bat"); ProcessBuilder pb = new ProcessBuilder(list); Process p = pb.start(); p.waitFor(); int returnValue = p.exitValue(); System.exit(returnValue); } }
You can run the .bat
file from the command prompt correctly.
Cause
The PowerShell script in .bat
file uses the $input
automatic variable. It reads input from STDIN, so it will wait for input from STDIN.
You can reproduce this problem with a .bat
file like this:
powershell.exe -Command "$input"
Solution
- You can use another
.bat
file that doesn't use$input
: www.pg-fl.jp - If you want to use
PSCommandPath
and$PSScriptRoot
in the PowerShell script, you can do like this:
@setlocal enableextensions enabledelayedexpansion & set "THIS_PATH=%~f0" & PowerShell.exe -Command "& (iex -Command ('{$PSCommandPath=\"%~f0\"; $PSScriptRoot=\"%~dp0"; #' + ((gc '!THIS_PATH:'=''!') -join \"`n\") + '}'))" %* & exit /b !errorlevel!
- You have to close STDIN when a PowerShell script in
.bat
file uses$input
like:
package org.example; import java.io.IOException; import java.util.ArrayList; import java.util.List; public class Main { public static void main(String[] args) throws IOException, InterruptedException { List<String> list = new ArrayList<String>(); list.add("c:/tmp/hoge.bat"); ProcessBuilder pb = new ProcessBuilder(list); Process p = pb.start(); p.getOutputStream().close(); // Close STDIN p.waitFor(); int returnValue = p.exitValue(); System.exit(returnValue); } }