Today I want to invoke WMIC command from java program (through Runtim
e.getRuntime().exec(.....)).
I use the following code, but unfortunately, my java appears to "deadlock".
public void testWMIC(){
final String command = "cmd /c wmic.exe Process get processid /format:csv";
ProcessExecutor executor = new ProcessExecutor(command, ProcessExecutor.class);
executor.start();
executor.waitFor(500);
}
I search many web sites, read the instructions about how to use Runtime.exec() in Java, but there was no hint for this issue.
Finally, I found a website, which said that sometimes the program invoked by command does NOT "Stop".
Although I feel it is ridiculous, I tried the following command. This time everything works OK.
final String command = "cmd /c wmic.exe Process get processid /format:csv <NUL";
Reference Code 1

Reference Code
import java.io.IOException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ProcessExecutor extends Thread {
protected Logger _log;
private String command;
private Process child;
private boolean isValidProcess = true;
public ProcessExecutor(String command, Class logType) {
_log = LoggerFactory.getLogger(logType);
this.command = command;
}
public Process getChildProcess() {
if ((child == null) || (isValidProcess)) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return child;
}
public void waitFor(long time) {
long times = time / 100;
while (isAlive()&&(times>0)) {
try {
Thread.sleep(100);
times--;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void run() {
child = null;
isValidProcess = true;
_log.info("New Invocation Command is {}", command);
child = exec(command);
if (child == null) {
isValidProcess = false;
return;
}
final StreamGlobber s1 = new StreamGlobber(_log,
java.util.logging.Level.INFO, child.getInputStream());
final StreamGlobber s2 = new StreamGlobber(_log,
java.util.logging.Level.SEVERE, child.getErrorStream());
s1.start();
s2.start();
try {
if (child != null) {
child.waitFor();
}
} catch (final InterruptedException e) {
e.printStackTrace();
}
}
private Process exec(String command) {
Runtime run = Runtime.getRuntime();
try {
return run.exec(command);
} catch (IOException e) {
_log.error(e.getMessage());
return null;
}
}
}
Reference Code 2

Reference Code
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.logging.Level;
import org.slf4j.Logger;
public class StreamGlobber implements Runnable {
private Level _level;
private InputStream _is;
private Thread _thread;
private Logger _log;
private boolean alive;
public StreamGlobber(final Logger log, final Level level,
final InputStream is) {
this._log = log;
this._level = level;
this._is = is;
}
public void start() {
_thread = new Thread(this);
alive = true;
_thread.start();
}
public boolean isAlive(){
return alive;
}
public void run() {
try {
InputStreamReader isr = new InputStreamReader(_is);
BufferedReader br = new BufferedReader(isr);
while (true) {
String s = br.readLine();
if (s == null)
break;
if (_level.equals(Level.SEVERE)) {
this._log.error(s);
} else {
this._log.info(s);
}
}
alive = false;
_is.close();
} catch (Exception ex) {
_log.error(ex.getMessage(), ex);
}
}
}
The reason why Java programmers need "<NUL" is that the program should explicitly close the output Stream of new created process. Unless the WMIC tool will not be executed.
回复删除So in other words, you can also use the following code to run WMIC in java:
String command = "cmd /c wmic ..... ";
Process process = getRuntime().exec(command);
process.getOutputStream().close();
.... (continue on redirecting inputstream and errorstream to your own printstreams)