Java ProcessBuilder Syntax for Initial construction with Command - java

I am trying to run a command which I give my ProcesBuilder as parameter while constructing.
The command is the following:
wmic process where name='OUTLOOK.EXE' get CommandLine
I normally just would run it with a pb.command() but I need to "catch" the output which I already did via a BufferedReader.
So my question is how I can do the Syntax right if I want to do something like:
ProcessBuilder pb = new ProcessBuilder("wmic process where name='OUTLOOK.EXE' get CommandLine");
I know I have to split this up somehow but I can't figure out how.
full method looks like :
public static void sendmail() throws IOException {
ProcessBuilder pb = new ProcessBuilder("wmic process where name='OUTLOOK.EXE' get CommandLine");
final Process p=pb.start();
BufferedReader br=new BufferedReader(new InputStreamReader(p.getInputStream()));
String line;
StringBuilder sb = new StringBuilder();
while((line=br.readLine())!=null) sb.append(line);
System.out.println(sb.toString());
}

Separate the command argument should work.
import java.io.IOException;
public class WmicProcessRunner {
public static void main(String[] args) {
try {
ProcessBuilder processBuilder = new ProcessBuilder("wmic", "process", "where", "name='OUTLOOK.EXE'", "get",
"CommandLine");
processBuilder.inheritIO();
Process wmicProcess = processBuilder.start();
while (wmicProcess.isAlive()) {
Thread.sleep(1000);
}
wmicProcess.destroy();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

Related

Java: Redirecting output of .bat file in other text file using exec() method?

Java is new to me.
I am executing a batch file using Runtime.getRuntime.exec(filename.bat) and this batch file executes a commandant encrypt.password -Dvalue=somevalue>log.txt and redirects its output to a log.txt file.
Problem that I am facing is batch file is working fine if I run it manually however when program executes it ,it just creates blank 'log.txt'
Content of mybat.bat batch file is as below:
cd/
c:
cd c:/ant_builds/thinclient
ant encrypt.password -Dvalue=someValue >C:/log.txt
Java code is as below:
Process p=Runtime.getRuntime.exec("C:\mybat.bat");
p.waitFor();
It seems that after creating the log file,meantime command is executing control comes out from process.
I have read almost 50 threads here however did not get the solution. Please help me out.
Use ProcessBuilder to create your process and call redirectOutput(File) to redirect and append output to a file.
Try this code:
public class Test {
ProcessBuilder builder;
Path log;
public Test() {
try
{
log = Paths.get("C:\\log.txt");
if (!Files.exists(log))
{
Files.createFile(log);
}
builder = new ProcessBuilder("ant", "encrypt.password", "-Dvalue=someValue");
builder.directory(Paths.get("C:\\ant_builds\\thinclient").toFile());
builder.redirectOutput(ProcessBuilder.Redirect.appendTo(log.toFile()));
builder.start();
}
catch (IOException e)
{
e.printStackTrace();
}
}
public static void main(String[] args) {
new Test();
}
}
For jdk 1.6 or less, use the following code:
public class Test {
ProcessBuilder builder;
Path log;
Process process;
BufferedReader br;
PrintWriter pw;
Charset charset = Charset.forName("UTF-8");
public Test() {
try {
log = new File("C:\\log.txt");
if (!log.exists()) {
log.createNewFile();
}
builder = new ProcessBuilder("ant", "encrypt.password","-Dvalue=someValue");
builder.directory(new File("C:\\ant_builds\\thinclient"));
builder.redirectErrorStream(true);
process = builder.start();
br = new BufferedReader(new InputStreamReader(process.getInputStream(),charset));
pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream(log, true), charset));
(new Thread() {
public void run() {
try {
while (process.isAlive()) {
String s = null;
while ((s = br.readLine()) != null) {
pw.print(s);
pw.flush();
}
}
br.close();
pw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
new Test();
}
}
I'm not sure about the order and list of ProcessBuilder arguments so try to play with them to get your code working.
You can also read commands from a common file and redirect output and erros to a sepearate files. Redirect.appendTo is to avoid the process from overiting the existing logs.
Try this code:
try {
File commands = new File("D:/Sample/Commands.txt");
File output = new File("D:/Sample/Output.txt");
File errors = new File("D:/Sample/ErrorsLog.txt");
ProcessBuilder pb = new ProcessBuilder("cmd");
System.out.println(pb.redirectInput());
System.out.println(pb.redirectOutput());
System.out.println(pb.redirectError());
pb.redirectInput(commands);
pb.redirectError(Redirect.appendTo(errors));
pb.redirectOutput(Redirect.appendTo(output));
pb.redirectInput();
pb.redirectOutput();
pb.redirectError();
pb.start();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

Runtime Process BufferedReader not outputting all lines (Psexec)

I am trying to read the output of Psexec into Java using a BufferedReader on a Process InputStream for use on a network however it is only outputting the first line.
Runtime rt = Runtime.getRuntime();
try {
Process p = rt.exec("C:\\Users\\*****\\Desktop\\PS\\Psexec \\\\" + "******" + " -u ****** -p ****** cmd /c dir D:\\");
BufferedReader stdInput = new BufferedReader(new InputStreamReader(p.getInputStream()));
log.add("Computer: " + address);
String s = null;
while ((s = stdInput.readLine()) != null) {
log.add(s);
}
} catch (IOException e) {
e.printStackTrace();
}
What would be the reason for this happening and how would this be fixed?
The process is probably producing some of its output on stderr. Either read both the output and the error streams, in separate threads, or use the ProcessBuilder to create the Process, and merge the output streams before you do so, with redirectErrorStream().
So, I spent some time playing around with this, using ProcessBuilder.
I tried redirecting the IO through the INHERITED and PIPE options, but could not get it to display the output of the remote command (the psexec content was fine)
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
public class Test1 {
public static void main(String[] args) {
ProcessBuilder pb = new ProcessBuilder(
"C:\\Users\\shane\\Downloads\\PSTools\\PsExec.exe",
"\\\\builder",
"-u",
"xxx",
"-p",
"xxx",
"cmd",
"/c", "dir", "c:\\"
);
try {
Process p = pb.start();
StreamConsumer.consume(p.getErrorStream());
StreamConsumer.consume(p.getInputStream());
System.out.println("Exited with :" + p.waitFor());
} catch (IOException | InterruptedException exp) {
exp.printStackTrace();
}
}
public static class StreamConsumer implements Runnable {
private InputStream is;
public StreamConsumer(InputStream is) {
this.is = is;
}
public static void consume(InputStream is) {
StreamConsumer consumer = new StreamConsumer(is);
new Thread(consumer).start();
}
#Override
public void run() {
try {
int in = -1;
while ((in = is.read()) != -1) {
System.out.print((char)in);
}
} catch (IOException exp) {
exp.printStackTrace();
}
}
}
}
I even tried redirecting the InputStreams to File without any success. It would seem that whatever mechanism psexec is using to stream the results from the remote machine don't seem to be picked up by Java.
You might try PAExec which did work, but didn't seem to wait to exit after the remote command exited...
It could be the case that you started the process and didn't wait for it to finish before checking it's output. If this is the case, your main thread will exit your while loop because it reads null even though the subprocess is still executing. I would suggest using Process.waitFor() so that all of the output ends up in the stream before you begin polling it.

Cannot get the getInputStream from Runtime.getRunTime.exec()

public class LinuxInteractor {
public static String executeCommand(String command)
{
System.out.println("Linux command: " + command);
try
{
Process p = Runtime.getRuntime().exec(command);
p.waitFor();
BufferedReader bf=new BufferedReader(new InputStreamReader( p.getInputStream()));
String str=bf.readLine();
System.out.println("inputStream is::"+str);
while( (str=bf.readLine()) != null)
{
System.out.println("input stream is::"+str);
}
System.out.println("process started");
}
catch (Exception e) {
System.out.println("Error occured while executing Linux command. Error Description: "
+ e.getMessage());
e.printStackTrace();
}
}
When I run the script through console, it's working. But through Java program InputStream(Str) is coming as null.
Is there any other approach I can use?
Solution
You should try to do the reading and the executing on different threads.
A better alternative is to use a ProcessBuilder, which takes care of the "dirty" work for you.
The code inside the try block could look something like this:
/* Create the ProcessBuilder */
ProcessBuilder pb = new ProcessBuilder(commandArr);
pb.redirectErrorStream(true);
/* Start the process */
Process proc = pb.start();
System.out.println("Process started !");
/* Read the process's output */
String line;
BufferedReader in = new BufferedReader(new InputStreamReader(
proc.getInputStream()));
while ((line = in.readLine()) != null) {
System.out.println(line);
}
/* Clean-up */
proc.destroy();
System.out.println("Process ended !");
See, also, this short demo.
Cause of the problem
According to the Java Docs, waitFor():
causes the current thread to wait, if necessary, until the process represented by this Process object has terminated.
So, you are trying to get the process's output-stream after it has terminated, therefore the null.
(Sorry for the major revamp of the answer.)
You need to do this in a separate thread:
Process process = Runtime.getRuntime().exec(command);
LogStreamReader lsr = new LogStreamReader(process.getInputStream());
Thread thread = new Thread(lsr, "LogStreamReader");
thread.start();
public class LogStreamReader implements Runnable {
private BufferedReader reader;
public LogStreamReader(InputStream is) {
this.reader = new BufferedReader(new InputStreamReader(is));
}
public void run() {
try {
String line = reader.readLine();
while (line != null) {
System.out.println(line);
line = reader.readLine();
}
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Then you need a second thread for input handling. And you might want to deal with stderr just like stdout.

Running a java program from another java program

I am working on a simple java program. It simply compiles and executes another java program. I am using Runtime.exec() function to compile and run. There is no problem with compilation. but when it runs, if the second program needs an input to read from keyboard, I can't give it from the master process. I used getOutputStream() function. but it couldn't help. I will provide my code.
public class sam {
public static void main(String[] args) throws Exception {
try {
Process p = Runtime.getRuntime().exec("javac sam2.java");
Process p2 = Runtime.getRuntime().exec("java sam2");
BufferedReader in = new BufferedReader(
new InputStreamReader(p2.getInputStream()));
OutputStream out = p.getOutputStream();
String line = null;
line = in.readLine();
System.out.println(line);
input=input+"\n";
out.write(input.getBytes());
p.wait(10000);
out.flush();
}catch (IOException e) {
e.printStackTrace();
}
}
}
This is my master program(sam.java).
The following is the code of sam2.java
public class sam2 {
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String str;
System.out.println("Enter the number..\n");
str = br.readLine();
System.out.println(Integer.parseInt(str));
}
}
There is no problem, if my second program has only printing statements. But the problem arises when I have to read something from the other.
It is a bit strange but you can run the second program without forking it. Just calling the main method in it. So forget the runtime section and do this:
sam2.main(new String[0]);
Of course this way you must compile sam2 at compile time
Each process needs to be allowed to run and finish. You can use Process#waitFor for this purpose. Equally, you need to consume any output from the process at the same time. waitFor will block so you will need use a Thread to read the input (and if you need to, write output to the process)
Depending on the location of the java/class file, you may also need to specify a starting folder from which the execution of the process can start.
Most of this significantly easier using ProcessBuilder
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
public class CompileAndRun {
public static void main(String[] args) {
new CompileAndRun();
}
public CompileAndRun() {
try {
int result = compile("compileandrun/HelloWorld.java");
System.out.println("javac returned " + result);
result = run("compileandrun.HelloWorld");
} catch (IOException | InterruptedException ex) {
ex.printStackTrace();
}
}
public int run(String clazz) throws IOException, InterruptedException {
ProcessBuilder pb = new ProcessBuilder("java", clazz);
pb.redirectError();
pb.directory(new File("src"));
Process p = pb.start();
InputStreamConsumer consumer = new InputStreamConsumer(p.getInputStream());
consumer.start();
int result = p.waitFor();
consumer.join();
System.out.println(consumer.getOutput());
return result;
}
public int compile(String file) throws IOException, InterruptedException {
ProcessBuilder pb = new ProcessBuilder("javac", file);
pb.redirectError();
pb.directory(new File("src"));
Process p = pb.start();
InputStreamConsumer consumer = new InputStreamConsumer(p.getInputStream());
consumer.start();
int result = p.waitFor();
consumer.join();
System.out.println(consumer.getOutput());
return result;
}
public class InputStreamConsumer extends Thread {
private InputStream is;
private IOException exp;
private StringBuilder output;
public InputStreamConsumer(InputStream is) {
this.is = is;
}
#Override
public void run() {
int in = -1;
output = new StringBuilder(64);
try {
while ((in = is.read()) != -1) {
output.append((char) in);
}
} catch (IOException ex) {
ex.printStackTrace();
exp = ex;
}
}
public StringBuilder getOutput() {
return output;
}
public IOException getException() {
return exp;
}
}
}
Now obviously, you should check the return results of the processes, and may be produce a better mechanism for interacting with the processes, but that's the basic idea...
You can just call the main method of the second class. The main method is just like any other static method.
This is what worked for me:
try {
single.main(new String[0]);
} catch (Exception e) {
JOptionPane.showMessageDialog(null, e);
}
Just call the main class file. For example, if your java class file name is xyz.java, you can call and execute the same in java swing application on click of a JButton, code is
private void Btn_createdatabaseActionPerformed(java.awt.event.ActionEvent evt) {
xyz.main(new String[0]);
}
That's it...

How to run Linux commands in Java?

I want to create diff of two files. I tried searching for code in Java that does it, but didnt find any simple code/ utility code for this. Hence, I thought if I can somehow run linux diff/sdiff command from my java code and make it return a file that stores the diff then it would be great.
Suppose there are two files fileA and fileB. I should be able to store their diff in a file called fileDiff through my java code. Then fetching data from fileDiff would be no big deal.
You can use java.lang.Runtime.exec to run simple code. This gives you back a Process and you can read its standard output directly without having to temporarily store the output on disk.
For example, here's a complete program that will showcase how to do it:
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class testprog {
public static void main(String args[]) {
String s;
Process p;
try {
p = Runtime.getRuntime().exec("ls -aF");
BufferedReader br = new BufferedReader(
new InputStreamReader(p.getInputStream()));
while ((s = br.readLine()) != null)
System.out.println("line: " + s);
p.waitFor();
System.out.println ("exit: " + p.exitValue());
p.destroy();
} catch (Exception e) {}
}
}
When compiled and run, it outputs:
line: ./
line: ../
line: .classpath*
line: .project*
line: bin/
line: src/
exit: 0
as expected.
You can also get the error stream for the process standard error, and output stream for the process standard input, confusingly enough. In this context, the input and output are reversed since it's input from the process to this one (i.e., the standard output of the process).
If you want to merge the process standard output and error from Java (as opposed to using 2>&1 in the actual command), you should look into ProcessBuilder.
You can also write a shell script file and invoke that file from the java code. as shown below
{
Process proc = Runtime.getRuntime().exec("./your_script.sh");
proc.waitFor();
}
Write the linux commands in the script file, once the execution is over you can read the diff file in Java.
The advantage with this approach is you can change the commands with out changing java code.
You need not store the diff in a 3rd file and then read from in. Instead you make use of the Runtime.exec
Process p = Runtime.getRuntime().exec("diff fileA fileB");
BufferedReader stdInput = new BufferedReader(new InputStreamReader(p.getInputStream()));
while ((s = stdInput.readLine()) != null) {
System.out.println(s);
}
try to use unix4j. it s about a library in java to run linux command. for instance if you got a command like:
cat test.txt | grep "Tuesday" | sed "s/kilogram/kg/g" | sort
in this program will become:
Unix4j.cat("test.txt").grep("Tuesday").sed("s/kilogram/kg/g").sort();
You can call run-time commands from java for both Windows and Linux.
import java.io.*;
public class Test{
public static void main(String[] args)
{
try
{
Process process = Runtime.getRuntime().exec("pwd"); // for Linux
//Process process = Runtime.getRuntime().exec("cmd /c dir"); //for Windows
process.waitFor();
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line;
while ((line=reader.readLine())!=null)
{
System.out.println(line);
}
}
catch(Exception e)
{
System.out.println(e);
}
finally
{
process.destroy();
}
}
}
Hope it Helps.. :)
Runtime run = Runtime.getRuntime();
//The best possible I found is to construct a command which you want to execute
//as a string and use that in exec. If the batch file takes command line arguments
//the command can be constructed a array of strings and pass the array as input to
//the exec method. The command can also be passed externally as input to the method.
Process p = null;
String cmd = "ls";
try {
p = run.exec(cmd);
p.getErrorStream();
p.waitFor();
}
catch (IOException e) {
e.printStackTrace();
System.out.println("ERROR.RUNNING.CMD");
}finally{
p.destroy();
}
The suggested solutions could be optimized using commons.io, handling the error stream, and using Exceptions. I would suggest to wrap like this for use in Java 8 or later:
public static List<String> execute(final String command) throws ExecutionFailedException, InterruptedException, IOException {
try {
return execute(command, 0, null, false);
} catch (ExecutionTimeoutException e) { return null; } /* Impossible case! */
}
public static List<String> execute(final String command, final long timeout, final TimeUnit timeUnit) throws ExecutionFailedException, ExecutionTimeoutException, InterruptedException, IOException {
return execute(command, 0, null, true);
}
public static List<String> execute(final String command, final long timeout, final TimeUnit timeUnit, boolean destroyOnTimeout) throws ExecutionFailedException, ExecutionTimeoutException, InterruptedException, IOException {
Process process = new ProcessBuilder().command("bash", "-c", command).start();
if(timeUnit != null) {
if(process.waitFor(timeout, timeUnit)) {
if(process.exitValue() == 0) {
return IOUtils.readLines(process.getInputStream(), StandardCharsets.UTF_8);
} else {
throw new ExecutionFailedException("Execution failed: " + command, process.exitValue(), IOUtils.readLines(process.getInputStream(), StandardCharsets.UTF_8));
}
} else {
if(destroyOnTimeout) process.destroy();
throw new ExecutionTimeoutException("Execution timed out: " + command);
}
} else {
if(process.waitFor() == 0) {
return IOUtils.readLines(process.getInputStream(), StandardCharsets.UTF_8);
} else {
throw new ExecutionFailedException("Execution failed: " + command, process.exitValue(), IOUtils.readLines(process.getInputStream(), StandardCharsets.UTF_8));
}
}
}
public static class ExecutionFailedException extends Exception {
private static final long serialVersionUID = 1951044996696304510L;
private final int exitCode;
private final List<String> errorOutput;
public ExecutionFailedException(final String message, final int exitCode, final List<String> errorOutput) {
super(message);
this.exitCode = exitCode;
this.errorOutput = errorOutput;
}
public int getExitCode() {
return this.exitCode;
}
public List<String> getErrorOutput() {
return this.errorOutput;
}
}
public static class ExecutionTimeoutException extends Exception {
private static final long serialVersionUID = 4428595769718054862L;
public ExecutionTimeoutException(final String message) {
super(message);
}
}
if the opening in windows
try {
//chm file address
String chmFile = System.getProperty("user.dir") + "/chm/sample.chm";
Desktop.getDesktop().open(new File(chmFile));
} catch (IOException ex) {
Logger.getLogger(Frame.class.getName()).log(Level.SEVERE, null, ex);
{
JOptionPane.showMessageDialog(null, "Terjadi Kesalahan", "Error", JOptionPane.WARNING_MESSAGE);
}
}
ProcessBuilder processBuilder = new ProcessBuilder();
// -- Linux --
// Run a shell command
processBuilder.command("bash", "-c", "ls /home/kk/");
// Run a shell script
//processBuilder.command("path/to/hello.sh");
// -- Windows --
// Run a command
//processBuilder.command("cmd.exe", "/c", "dir C:\\Users\\kk");
// Run a bat file
//processBuilder.command("C:\\Users\\kk\\hello.bat");
try {
Process process = processBuilder.start();
StringBuilder output = new StringBuilder();
BufferedReader reader = new BufferedReader(
new InputStreamReader(process.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
output.append(line + "\n");
}
int exitVal = process.waitFor();
if (exitVal == 0) {
System.out.println("Success!");
System.out.println(output);
System.exit(0);
} else {
//abnormal...
}
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}

Categories