Passing command prompt functions from java - java

I want to get the result of windows command prompt function from Java.
Java code:
Process process2 = Runtime.getRuntime().exec("cmd /c getmac");
Are there any alternative libraries available other than Runtime?

Use Apache Commons Exec. It can be used to get a console output of the running process.
A part of code from a real project
private final Executor executor = new DefaultExecutor();
private final ExecuteWatchdog watchDog = new ExecuteWatchdog(ExecuteWatchdog.INFINITE_TIMEOUT);
private final ProcessDestroyer shutdownHookProcessDestroyer = new ShutdownHookProcessDestroyer();
private final DefaultExecuteResultHandler resultHandler = new DefaultExecuteResultHandler() {
#Override
public void onProcessFailed(ExecuteException ex) {
super.onProcessFailed(ex);
LOG.error("Error executing xxx.exe", ex);
}
};
public void startInSaveRecordMode(Long callId, File pathToResult) throws IOException {
CommandLine commandLine = createModeUserPasswordCommandLine(SAVE_RECORD_MODE_COMMAND)
.addArgument(ValidationUtil.toString(callId)).addArgument(
ValidationUtil.toString(pathToResult));
execute(commandLine);
}
private void execute(CommandLine commandLine) throws IOException {
Assert.notNull(pathToProcess);
executor.setWatchdog(watchDog);
executor.setProcessDestroyer(shutdownHookProcessDestroyer);
executor.setStreamHandler(createStreamHandler());
if (LOG.isDebugEnabled()) {
LOG.debug("Executing " + commandLine);
}
executor.execute(commandLine, resultHandler);
}
private CommandLine createModeUserPasswordCommandLine(String mode) {
Assert.hasLength(sensormUser);
Assert.notNull(sensormPassword);
return createCommandLine().addArgument(mode).addArgument(sensormUser);
}
private CommandLine createCommandLine() {
return new CommandLine(pathToProcess);
}
private ExecuteStreamHandler createStreamHandler() {
OutputEventsHandler eventsHandler = new OutputEventsHandler(eventsQueue);
SensormLogHandler errorLogHandler = new SensormLogHandler(LOG, Level.ERROR);
return new PumpStreamHandler(eventsHandler, errorLogHandler);
}
public int waitFor() throws InterruptedException {
resultHandler.waitFor();
return resultHandler.getExitValue();
}

Related

How to destroy process when it is passed as constructor parameter

I have implemented a way to timeout my process running iperf server side based on this question's top answear and it works as intended but I am not sure how to destroy a process object that I pass inside Task's class constructor.
This is my modified code:
public class Main {
public static void main(String[] args) throws IOException {
Process p=null;
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<String> future = executor.submit(new Task(p));
try {
System.out.println("Started..");
System.out.println(future.get(5, TimeUnit.SECONDS));
System.out.println("Finished!");
} catch (TimeoutException | InterruptedException | ExecutionException e) {
future.cancel(true);
//gives NullPointerException as expected after thread times out
p.destroyForcibly();
System.out.println("Terminated!");
}
executor.shutdownNow();
}
}
class Task implements Callable<String> {
Process p;
public Task(Process p) {
this.p = p;
}
#Override
public String call() throws Exception {
String s;
String toDisplay = "";
this.p = Runtime.getRuntime().exec("iperf3.exe -s -1");
BufferedReader br = new BufferedReader(new InputStreamReader(this.p.getInputStream()));
while ((s = br.readLine()) != null) {
toDisplay += s + "\n";
}
p.destroyForcibly();
return toDisplay;
}
}
I am guessing I should somehow set main's Process but I have no idea how to aproach this problem

Running Git from command Line

I want to revert a merge by calling the 'git revert -m 1 ' command in cmd from Java. The code below reverts it and prints the output on console as OutputStream. I want a notification from Git in Java whether the revert is successful or not. How can I get it in say String or boolean format?
public void revert(String path, String CommitId) throws IOException, Exception
{
String revertCommand="git revert -m 1 "+CommitId;
String commitCommand="git commit -m "+'"'+"Reverted a commit"+'"';
//revert the commit in that branch
String[] command =
{
"cmd",
};
Process p = Runtime.getRuntime().exec(command);
new Thread(new SyncPipe(p.getErrorStream(), System.err)).start();
new Thread(new SyncPipe(p.getInputStream(), System.out)).start();
PrintWriter stdin = new PrintWriter(p.getOutputStream());
stdin.println(path);
stdin.println("git checkout -b tempBranch release/2017.1");
stdin.println(revertCommand);
stdin.println(commitCommand);
stdin.println("git push contrib/WMD-202817 tempBranch");
// write any other commands you want here
stdin.close();
int returnCode = p.waitFor();
System.out.println("Return code = " + returnCode);
}
public class SyncPipe implements Runnable {
public SyncPipe(InputStream istrm, OutputStream ostrm) {
istrm_ = istrm;
ostrm_ = ostrm;
}
public void run() {
try
{
final byte[] buffer = new byte[1024];
for (int length = 0; (length = istrm_.read(buffer)) != -1; )
{
ostrm_.write(buffer, 0, length);
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
private final OutputStream ostrm_;
private final InputStream istrm_;
}

Using Commons Exec for context-sensitive execution

What I'm trying to do is simply run a batch file that does some preparatory work necessary for the subsequent commands to be executed successfully (setting environment variables and stuff). To prove this I put together a sample that uses Commons Exec
public class Tester {
public static void main(String[] args) throws Exception {
Tester tester = new Tester();
MyResultHandler handler = tester.new MyResultHandler();
CommandLine commandLine = CommandLine.parse("bash");
PipedOutputStream ps = new PipedOutputStream();
PipedInputStream is = new PipedInputStream(ps);
BufferedWriter os = new BufferedWriter(new OutputStreamWriter(ps));
Executor executor = new DefaultExecutor();
PumpStreamHandler ioh = new PumpStreamHandler(System.out, System.err, is);
executor.setStreamHandler(ioh);
ioh.start();
executor.execute(commandLine, handler);
os.write("export MY_VAR=test");
os.flush();
os.write("echo $MY_VAR");
os.flush();
os.close();
}
private class MyResultHandler extends DefaultExecuteResultHandler {
#Override
public void onProcessComplete(final int exitValue) {
super.onProcessComplete(exitValue);
System.out.println("\nsuccess");
}
#Override
public void onProcessFailed(final ExecuteException e) {
super.onProcessFailed(e);
e.printStackTrace();
}
}
}
But that prints empty string instead of the word "test". Any clues?
Answering my own question based on feedback from another forum. The trick is to add a new line character at the end of each command like this:
os.write("export MY_VAR=test\n");
os.flush();
os.write("echo $MY_VAR\n");

How to Stop a Running a Program Using Other Java Program

I have been implementing a program to compile and run other applications. I was wondering if there is a way to terminate a program when my application discovers that there is an issue e.g. infinite loop. I tried to using process.Destroy() but it kills the CMD not that actual program that has infinite loop...
Your help is really appreciated.
Here is a part of my code:
synchronized (pro) {
pro.wait(30000);
}
try{
pro.exitValue();
}catch (IllegalThreadStateException ex)
{
pro.destroy();
timeLimitExceededflag = true;
System.out.println("NOT FINISHED123");
System.exit(0);
}
}
Basically I am making my application to invoke the cmd using a processBuilder. This code terminates the CMD but if it runs a program that has an infinite loop that application will be still running which affects my servers performance.
I'd suggest to use the following solution:
start your program with a title specified
get PID of the process using "tasklist" command. A CSV parser required. There are tons of available I believe, like org.apache.commons.csv.CSVParser etc :)
kill the process by "taskkill" command using PID.
Here is some part of code which may be useful:
public static final String NL = System.getProperty("line.separator", "\n");
public <T extends Appendable> int command(String... cmd) throws Exception {
return command(null, cmd);
}
public <T extends Appendable> int command(T out, String... cmd) throws Exception {
try {
final ProcessBuilder pb = new ProcessBuilder(cmd);
pb.redirectErrorStream(true);
final Process proc = pb.start();
final BufferedReader rd = new BufferedReader(new InputStreamReader(proc.getInputStream()));
for (;;) {
final String line = rd.readLine();
if (line == null) {
break;
}
if (out != null) {
out.append(line);
out.append(NL);
}
}
return proc.waitFor();
} catch (InterruptedException e) {
throw new IOException(e);
}
}
public void startProcessWithTitle(String pathToExe, String title) throws Exception {
command("cmd.exe", "/C", "start", '"' + pathToExe + '"', '"' + title + '"', ..cmd.params..);
}
public int findProcessByTitle(String title) throws Exception {
final StringBuilder list = new StringBuilder();
if (command(list, "tasklist", "/V", "/FO", "csv") != 0) {
throw new RuntimeException("Cannot get tasklist. " + list.toString());
}
final CSVReader csv = new CSVReader(new StringReader(list.toString()), ',', true, "WindowsOS.findProcessByTitle");
csv.readHeaders(true); // headers
int pidIndex = csv.getHeaderIndex("PID");
int titleIndex = csv.getHeaderIndex("Window Title");
while (csv.nextLine()) {
final String ttl = csv.getString(titleIndex, true);
if (ttl.contains(title)) {
return csv.getInt(pidIndex);
}
}
Utils.close(csv);
return -1;
}
public boolean killProcess(int pid) throws Exception {
return command("taskkill", "/T", "/F", "/PID", Integer.toString(pid)) == 0;
}

How to find and kill running Win-Processes from within Java?

I need a Java way to find a running Win process from which I know to name of the executable. I want to look whether it is running right now and I need a way to kill the process if I found it.
private static final String TASKLIST = "tasklist";
private static final String KILL = "taskkill /F /IM ";
public static boolean isProcessRunning(String serviceName) throws Exception {
Process p = Runtime.getRuntime().exec(TASKLIST);
BufferedReader reader = new BufferedReader(new InputStreamReader(
p.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
if (line.contains(serviceName)) {
return true;
}
}
return false;
}
public static void killProcess(String serviceName) throws Exception {
Runtime.getRuntime().exec(KILL + serviceName);
}
EXAMPLE:
public static void main(String args[]) throws Exception {
String processName = "WINWORD.EXE";
//System.out.print(isProcessRunning(processName));
if (isProcessRunning(processName)) {
killProcess(processName);
}
}
You can use command line windows tools tasklist and taskkill and call them from Java using Runtime.exec().
Here's a groovy way of doing it:
final Process jpsProcess = "cmd /c jps".execute()
final BufferedReader reader = new BufferedReader(new InputStreamReader(jpsProcess.getInputStream()));
def jarFileName = "FileName.jar"
def processId = null
reader.eachLine {
if (it.contains(jarFileName)) {
def args = it.split(" ")
if (processId != null) {
throw new IllegalStateException("Multiple processes found executing ${jarFileName} ids: ${processId} and ${args[0]}")
} else {
processId = args[0]
}
}
}
if (processId != null) {
def killCommand = "cmd /c TASKKILL /F /PID ${processId}"
def killProcess = killCommand.execute()
def stdout = new StringBuilder()
def stderr = new StringBuilder()
killProcess.consumeProcessOutput(stdout, stderr)
println(killCommand)
def errorOutput = stderr.toString()
if (!errorOutput.empty) {
println(errorOutput)
}
def stdOutput = stdout.toString()
if (!stdOutput.empty) {
println(stdOutput)
}
killProcess.waitFor()
} else {
System.err.println("Could not find process for jar ${jarFileName}")
}
There is a little API providing the desired functionality:
https://github.com/kohsuke/winp
Windows Process Library
You could use a command line tool for killing processes like SysInternals PsKill and SysInternals PsList.
You could also use the build-in tasklist.exe and taskkill.exe, but those are only available on Windows XP Professional and later (not in the Home Edition).
Use java.lang.Runtime.exec to execute the program.
Use the following class to kill a Windows process (if it is running). I'm using the force command line argument /F to make sure that the process specified by the /IM argument will be terminated.
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class WindowsProcess
{
private String processName;
public WindowsProcess(String processName)
{
this.processName = processName;
}
public void kill() throws Exception
{
if (isRunning())
{
getRuntime().exec("taskkill /F /IM " + processName);
}
}
private boolean isRunning() throws Exception
{
Process listTasksProcess = getRuntime().exec("tasklist");
BufferedReader tasksListReader = new BufferedReader(
new InputStreamReader(listTasksProcess.getInputStream()));
String tasksLine;
while ((tasksLine = tasksListReader.readLine()) != null)
{
if (tasksLine.contains(processName))
{
return true;
}
}
return false;
}
private Runtime getRuntime()
{
return Runtime.getRuntime();
}
}
You will have to call some native code, since IMHO there is no library that does it. Since JNI is cumbersome and hard you might try to use JNA (Java Native Access). https://jna.dev.java.net/
small change in answer written by Super kakes
private static final String KILL = "taskkill /IMF ";
Changed to ..
private static final String KILL = "taskkill /IM ";
/IMF option doesnot work .it does not kill notepad..while /IM option actually works

Categories