I want to open an application during run time in Mac using netbeans i used the following code but it throws exception. I used this code for windows with few changes i used it in Mac. Can anyone pls suggest me the correct code.
else
{
try {
Runtime r = Runtime.getRuntime();
p = Runtime.getRuntime().exec("/Applications/TextEdit.app /Users/apple/Documents/java files/scratch files/hi.rtf");
A4 a4sObj = new A4(new String[]{jComboBox2.getSelectedItem().toString()});
} catch (IOException ex) {
Logger.getLogger(serialportselection.class.getName()).log(Level.SEVERE, null, ex);
}
}
Okay, so that took a little bit of digging. It seems the preferred way to run a .app bundle is to use the open command. In order to get the app to open a file, you have to use the -a parameter, for example...
import java.io.IOException;
import java.io.InputStream;
public class Test {
public static void main(String[] args) {
String cmd = "/Applications/TextEdit.app";
//String cmd = "/Applications/Sublime Text 2.app";
String fileToEdit = "/Users/.../Documents/Test.txt";
System.out.println("Cmd = " + cmd);
ProcessBuilder pb = new ProcessBuilder("open", "-a", cmd, fileToEdit);
pb.redirectErrorStream(true);
try {
Process p = pb.start();
Thread t = new Thread(new InputStreamConsumer(p.getInputStream()));
t.start();
int exitCode = p.waitFor();
t.join();
System.out.println("Exited with " + exitCode);
} catch (IOException | InterruptedException ex) {
ex.printStackTrace();
}
}
public static class InputStreamConsumer implements Runnable {
private InputStream is;
public InputStreamConsumer(InputStream is) {
this.is = is;
}
#Override
public void run() {
int read = -1;
try {
while ((read = is.read()) != -1) {
System.out.print((char)read);
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
}
Related
I'm trying to get the result from a .class, calling the process on another .java. The formatting of both files is as follows:
package Ejemplo2;
import java.io.*;
public class Ejemplo2 {
public static void main(String[] args) throws IOException {
Process p = new ProcessBuilder("ls", "-la").start();
try {
InputStream is = p.getInputStream();
int c;
while ((c = is.read()) != -1) {
System.out.print((char) c);
}
is.close();
} catch (Exception e) {
e.printStackTrace();
}
int exitVal;
try {
exitVal = p.waitFor(); //recoge la salida de System.exit()
System.out.println("Valor de Salida: " +exitVal);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
and
package Ejemplo3;
import java.io.*;
public class Ejemplo3 {
public static void main(String[] args) throws IOException{
File directorio = new File("./out/production/psp-2122/Ejemplo2");
ProcessBuilder pb = new ProcessBuilder("java", "Ejemplo2");
pb.directory(directorio);
System.out.printf("Directorio de trabajo: %s%n",pb.directory());
Process p = pb.start();
try {
InputStream is = p.getInputStream();
for (int i = 0; i<is.available(); i++) {
System.out.println("" + is.read());
}
is.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
The result only displays the directory and the exit code, but I don't really have a clue why the process itself is not shown.
You should probably do:
// start in classes root
File directorio = new File("./out/production/psp-2122");
// Run java with fully qualified class name Ejemplo2.Ejemplo2
ProcessBuilder pb = new ProcessBuilder("java", "Ejemplo2.Ejemplo2");
You aren't seeing any of the error messages as you are not reading any of the error streams. The simplest approach is to just redirect standard ERROR -> OUTPUT before calling start():
ProcessBuilder pb = new ProcessBuilder(cmd);
pb.redirectErrorStream(true);
Process p = pb.start();
Save yourself some typing, replace the while / for loops through the standard output streams with:
try(var stdout = p.getInputStream()) {
stdout.transferTo(System.out);
}
Always call waitFor at the end so that you know the process completion:
int exitVal = pb.waitFor();
Process p = Runtime.getRuntime().exec("myexe.exe");
BufferedReader br = null;
try{
br = new BufferedReader(new InputStreamReader(p.getInputStream(), "GB2312"));
String value = null;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
}finally{
IOUtils.close(br);
}
Then, the output likes below, not the string I want:
Child: Can't read length for data, error code 109
It seems that the problem appears, because of the output of the exe which is too long. Can ProcessBuilder solve it ?
As a general rule of thumb, you should always read the output of Process before you call waitFor (or use a background Thread to read it while you waitFor)
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
public class PBDemo {
public static void main(String[] args) throws Exception {
String s;
ProcessBuilder pb = new ProcessBuilder("myexe.exe");
pb.redirectErrorStream(true);
try {
Process pro = pb.start();
InputConsumer ic = new InputConsumer(pro.getInputStream());
System.out.println("...Waiting");
int exitCode = pro.waitFor();
ic.join();
System.out.println("Process exited with " + exitCode);
} catch (Exception e) {
System.out.println("sorry" + e);
e.printStackTrace();
}
}
public static class InputConsumer extends Thread {
private InputStream is;
public InputConsumer(InputStream is) {
this.is = is;
start();
}
#Override
public void run() {
try {
int in = -1;
while ((in = is.read()) != -1) {
System.out.print((char) in);
}
} catch (IOException exp) {
exp.printStackTrace();
}
}
}
}
In the past, I've either provided an Observer Pattern to the InputConsumer, through which some other party can be notified as new input comes in or otherwised cached the output so I can process it after the process has completed, based on your needs
Recently I added "adb devices" in the nano ./bash_profile so that I can run it from any directory.
I used one java application to run
public static void main(String [] args) {
executeCmd("adb devices");
}
private static void executeCmd(String string) {
InputStream pipedOut = null;
try {
Process aProcess = Runtime.getRuntime().exec(string);
// These two thread shall stop by themself when the process end
Thread pipeThread = new Thread(new StreamGobber(aProcess.getInputStream()));
Thread errorThread = new Thread(new StreamGobber(aProcess.getErrorStream()));
pipeThread.start();
errorThread.start();
aProcess.waitFor();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException ie) {
ie.printStackTrace();
}
}
class StreamGobber implements Runnable {
private InputStream Pipe;
public StreamGobber(InputStream pipe) {
if(pipe == null) {
throw new NullPointerException("bad pipe");
}
Pipe = pipe;
}
public void run() {
try {
byte buffer[] = new byte[2048];
int read = Pipe.read(buffer);
while(read >= 0) {
System.out.write(buffer, 0, read);
read = Pipe.read(buffer);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if(Pipe != null) {
try {
Pipe.close();
} catch (IOException e) {
}
}
}
when I run any other commands such as "ls" it's working fine!!
I'm using mac ..
thanks :)
Maybe global path problem on mac. You can try run with absolute adb program path as command.
I want a java program to execute the following shell command:
apktool.jar d /path/to/my/app.apk
This command perfectly works when executing it directly on command line.
Java Code:
public static void main(String[] args) {
String command = "apktool d /path/to/my/app.apk";
try {
Runtime.getRuntime().exec(command);
} catch (IOException e1) {
e1.printStackTrace();
}
}
There is no error, no exception. Nothing happens and i have the impression that I already searched the entire internet for a solution. Does anybody know what I am doing wrong? A simple command like
mkdir /path/to/a/new/folder
works without problems.
I tried the same using ProcessBuilder:
try {
Process process = new ProcessBuilder(command).start();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
This time i only get "Cannot run program "apktool d /path/to/my/app.apk, No such file or directory". I can't even run the mkdir command.
You need to call the jar with java.exe, and you're not doing that. Also you need to trap the input and error streams from the process, something you can't do the way you're running this. Use ProcessBuilder instead, get your streams and then run the process.
For example (and I can only do a Windows example),
import java.io.IOException;
import java.io.InputStream;
import java.util.Scanner;
public class ProcessEg {
private static Process p;
public static void main(String[] args) {
String[] commands = {"cmd", "/c", "dir"};
ProcessBuilder pBuilder = new ProcessBuilder(commands);
pBuilder.redirectErrorStream();
try {
p = pBuilder.start();
InputStream in = p.getInputStream();
final Scanner scanner = new Scanner(in);
new Thread(new Runnable() {
public void run() {
while (scanner.hasNextLine()) {
System.out.println(scanner.nextLine());
}
scanner.close();
}
}).start();
} catch (IOException e) {
e.printStackTrace();
}
try {
int result = p.waitFor();
p.destroy();
System.out.println("exit result: " + result);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Try doing it like this:
StringBuffer output = new StringBuffer();
Process p;
try {
p = Runtime.getRuntime().exec("./path/apktool d /path/to/my/app.apk");
p.waitFor();
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = "";
while ((line = reader.readLine())!= null) {
output.append(line + "\n");
}
} catch (Exception e) {
e.printStackTrace();
}
system.out.println(output.toString());
Creating first a process allows you to wait for a response and reads the output of the execution of your process.
If something is failing while running your shell command, you will have the error printed at the end.
Also, make sure your java program can access your shell script, or better provide the full path to it like:
./path/to/shell/apktool d /path/to/my/app.apk
This code will execute an external exe application.
private void clientDataActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
try {
Runtime.getRuntime().exec("C:\\Program Files (x86)\\VideoLAN\\VLC\\vlc.exe");
} catch(Exception e) {
System.out.println(e.getMessage());
}
}
What if I want to execute external java file? Is it possible? For example like this command:
Runtime.getRuntime().exec("cmd.exe /C start cd \"C:\Users\sg552\Desktop\ java testfile");
The code does not work from java and cmd prompt. How to solve this?
First, you command line looks wrong. A execution command is not like a batch file, it won't execute a series of commands, but will execute a single command.
From the looks of things, you are trying to change the working directory of the command to be executed. A simpler solution would be to use ProcessBuilder, which will allow you to specify the starting directory for the given command...
For example...
try {
ProcessBuilder pb = new ProcessBuilder("java.exe", "testfile");
pb.directory(new File("C:\Users\sg552\Desktop"));
pb.redirectError();
Process p = pb.start();
InputStreamConsumer consumer = new InputStreamConsumer(p.getInputStream());
consumer.start();
p.waitFor();
consumer.join();
} catch (IOException | InterruptedException ex) {
ex.printStackTrace();
}
//...
public class InputStreamConsumer extends Thread {
private InputStream is;
private IOException exp;
public InputStreamConsumer(InputStream is) {
this.is = is;
}
#Override
public void run() {
int in = -1;
try {
while ((in = is.read()) != -1) {
System.out.println((char)in);
}
} catch (IOException ex) {
ex.printStackTrace();
exp = ex;
}
}
public IOException getException() {
return exp;
}
}
ProcessBuilder also makes it easier to deal with commands that might contain spaces in them, without all the messing about with escaping the quotes...