Java command Runtime.getRuntime().exec() in Mac OS - java

I´m using Mac OS Lion, with java version 1.6.0_26
I'm making a small app for Mac in Java with a main menu for the user, so he can choose several options.
One of them is install an app using a .pkg
Everything was working fine with these commands:
File instFolder = new File(System.getProperty("user.dir") + "/foldername/appInstaller.pkg");
String s = "open "+ instFolder.toString();
Process p = Runtime.getRuntime().exec(s);
Then I realized that there is a problem when foldername has spaces or if I copy this java file with the needed subfolders to a USB pen drive with "NO NAME" as name (or some name with spaces).
Because s will become something like:
open /Volumes/NO NAME/foldername/appInstaller.pkg
or
open /Users/user1/Desktop/folder name/appInstaller.pkg
So when you run the p process, the command will finish where the first space appears on the path
open /Volumes/NO
or
open /Users/user1/Desktop/folder
To try to fix this I changed the s definition for something like this:
String s = "open "+ "\"" + instFolder.toString() + "\"";
It stopped working fine. The strange thing is that if i copy the s value (after creating the s variable) and paste it in the terminal it works:
open "/Users/user1/Desktop/folder name/appInstaller.pkg"
but running it from Java it does't work.
Could you help me, please?
Thanks.

In order to properly escape arguments, you can use the following:
Runtime.getRuntime().exec(new String[] { "open", instFolder.toString() });
Though I would probably to use the more modern ProcessBuilder:
ProcessBuilder pb = new ProcessBuilder("open", instFolder.toString());
Process p = pb.start();
int exitCode = p.waitFor();
Though this may be worth a read depending on what you want to do with the processes output.
Note: edited to reflect question in comment

it seems your path does not have quotes when turned into the shell.
You should probably add "'" on both sides of your path, so the final shell command will look like:
open 'your path'
instead of
open your path

Here's a little trick that came out from the answers mentioned above:
ProcessBuilder pb = new ProcessBuilder(commandString.split(" "));
Say commandString = "killall Mail" then the split will separate the words making it a String[] parameter to the ProcessBuilder.

Related

unable to access jarfile using java Runtime from another jar on linux platform

I am trying to run an executable jar from another jar using Runtime.exec function from java class.
Code is
Runtime r = Runtime.getRuntime();
Process p = r.exec("java -jar \""+_JarPath +"\" " + "\""+ args[0]+"\""+ " " +"\""+ args[1]+"\""+ " " +"\""+ args[2]+"\"" + " " +"\""+ args[3]+"\"");
Here, argument argsare not null and are well defined.
This code runs fine on Windows platform but on Linux, I am getting error
Unable to access jarfile "/opt/mydir/lib/MyFol/mytest.jar"
I have read other similar questions and made sure that
The directory /opt/mydir/lib/MyFol/ and file mytest.jar are having all the permission
The executable jar from which this process command is launched is also having all the permissions.
User on linux is also admin
I am using OpenJDK on Linux.
The actual problem with the above code on linux machine was the double quotes, as stated by Robin Green in post, and he is right.
But then I was unable to run jar when the path contained empty spaces or other arguments were having spaces in between.
For that I had to try some other way to load jars, which could work seamless in both the platforms and had the problem of spaces removed too.
Process Builder came to rescue, in this situation.
ProcessBuilder pb = new ProcessBuilder("java", "-jar", _JarPath, args[0], args[1], args[2], args[3]);
Process p = pb.start();
This worked fine on both the platforms without any probes, in all the situations.
EDIT
OOPS an easy solution was there but I did not got it, Thanks to Ingo for the comment posted that we can pass the arguments by using another overloaded function of exec
Runtime r = Runtime.getRuntime();
Process p =null;
String[] cmdarray = new String[7];
cmdarray[0] = "java";
cmdarray[1] = "-jar";
cmdarray[2] = _JarPath;
cmdarray[3] = args[0];
cmdarray[4] = args[1];
cmdarray[5] = args[2];
cmdarray[6] = args[3];
p = r.exec(cmdarray);
Try it without the double quotes. I suspect it may be an issue that the shell is not being invoked, but rather Java is being invoked directly.

Can't launch .exe from Java

I am trying to launch a .exe file through a Java program. I used the following code:
System.out.println("Opening " + path);
Process exec;
exec = Runtime.getRuntime().exec("rundll32 SHELL32.DLL,ShellExec_RunDLL " + path);//path is the path of the exe file which is passed as an argument from another java class
the output is as follows:
Opening C:\Program Files (x86)\C-Free 5\CppIDE.exe
But it is not opening.
Instead when I try
String pat="C:\\Program Files (x86)\\C-Free 5\\CppIDE.exe";
Process exec;
exec = Runtime.getRuntime().exec("rundll32 SHELL32.DLL,ShellExec_RunDLL " + pat);
the program is opened.
I don't know what the problem is.
It's very likely that the space in your path is the problem.
I suggest you pass the arguments as an array instead of passing a single string containing the whole command (alternatively you could quote the spaces correctly, but that's not quite as easy).
Either
use the String[] version of Runtime.exec() or
switch to using ProcessBuilder which has an altogether simpler and more intuitive API.
With ProcessBuilder this could look like this:
ProcessBuilder pb = new ProcessBuilder("rundll32", "SHELL32.DLL,ShellExec_RunDLL", path);
Process p = pb.start();
Also, I see no reason to invoke rundll32 at all in this scenario. This should work just as well:
ProcessBuilder pb = new ProcessBuilder(path);
Process p = pb.start();
You need to construct the path using File.separator. The path separator you are using will, in this case, will be system dependant.

Having an Issue with running gnuplot processes from Java

I'm having some trouble running gnuplot processes from Java. I'm creating a gnuplot script file, and then running it from within a java program. I've tried using both Process Builder and building a precess using Runtime.getRuntime().exec("blah blah..."), and neither have the full capability to work. The funny thing is is that using Runtime to make the process works almost perfectly, as long as the image file I'm creating via gnuplot isn't being saved to a directory without a space in it's name. ProcessBuilder doesn't work at all, however, and gives me the error: "CreateProcess error=2, The system cannot find the file specified"
It's taken me far too long to figure this stuff out, and so any help would be appreciated.
The code I use is here:
File script = new File("Demo.plt"); //Script file that outputs to a PNG file
//This works as long as the script file doesn't output to a png with a space in it's filepath
Process aProcess = Runtime.getRuntime().exec("gnuplot " + script.toString());
Thread.currentThread().sleep(1000);
aProcess.waitFor();
//This doesn't work at all
ProcessBuilder builder = new ProcessBuilder("gnuplot " + script.toString());
builder.redirectErrorStream(true);
Process process = builder.start();
And I know that the script works if run outside of Java, regardless of the spaces in the output line. I've even tried using '\ ' (the escape character for a space) and that doesn't work either. In fact, here is the code that I use:
String graphName = "DemoGraph";
//Isolate the FilePath
String path = script.getPath();
path = path.replace(script.getName(),"");
path = path.replace(File.separator, "\\\\"); //Gets around any parsing errors in filepaths on Windows
path = path.replace(" ", "\\ "); //Should get around parsing errors with spaces in gnuplot, but it seems to be irrelevant.
scriptFileWriter.write("set output \"" + path + graphName + ".png\"\r\n");
It's got to be an issue with java, because the scripts run from the Windows command line, and from the gnuplot command line, and frun being run by double-clicking the
I forgot to put quotes around the file name. It was a STUPID error.

How to run bat file from java with arguments (i.e file name with full path) having folder name with space

Am trying to execute the a bat file with some arguments through a JAVA programmes . the arguments are file name with full path, And this path had some folder name with space, which are creating issue and giving me the following error
Error: 'D:\Documents' is not recognized as an internal or external
command
the code is as below
String command = "D:\Documents and Settings\ A.bat" + " " D:\Documents and Settings\B.xml
1. process = Runtime.getRuntime().exec(new String[] {"cmd.exe","/c",command});
2. process.waitFor();
3. exitValue = process.exitValue();
You need to escape the \ in your string (i.e. doubling them: D:\\Documents), but that is not the problem. You can try to escape the spaces Documents\\ and\\ Settings or you use the exec method that does this for you. Just dont build the command line by yourself. Better use ProcessBuilder for starting processes.
String command = "\"D:\Documents and Settings\\" A.bat" + " \"D:\Documents and Settings\B.xml\""
Escape double quotes, so you can include double quotes in the literal, to give:
cmd.exe /x "D:\Documents and Settings\" A.bat "D:\Documents and Settings\B.xml"
I was trying to do the same thing. I googled whole day but didn't make it work. At Last I handled it in this way, I am sharing it if it comes to any use of anybody :
String command = "A.bat D:\\Documents and Settings\\B.xml";
File commandDir = new File ( "D:\\Documents and Settings ");
String[] cmdArray = { "cmd.exe", "/c", command };
1. Process process = Runtime.getRuntime().exec( cmdArray, null, cmdArray );
2. process.waitFor();
3. exitValue = process.exitValue();
I've spent a while searching on SO and the wider Internet and was about to post this as a new question when I came across this, which does seem identical to my issue...
I am trying to call a Windows batch file from Java. The batch file takes several arguments but just the first, which is a path to a data file, is of relevance to this problem. The cut-down command line that I have been experimenting with is essentially:
cmd /c c:\path\to\my\batchfile.bat c:\path\to\my\datafile.mdl
I'm using Apache Commons Exec which ultimately delegates to Runtime.getRuntime().exec(String[] cmdarray, String[] envp, File dir), the 'correct' version as opposed to the overloaded versions taking a single String command. Quoting of the arguments when they contain spaces is therefore taken care of.
Now, both the path to the batch file and/or the path to the data file can have spaces in them. If either the path to the batch file or the path to the data file have spaces in, then the batch file is executed. But if both have spaces in them then the path to the batch file is truncated at the first space.
This has to be a (Java or Windows?) bug, right? I've debugged right down to the native call to create() in java.lang.ProcessImpl and all seems ok. I'm on JDK1.6.

Find the associated program to open a file using Java

I wish to open a file (lets say, a word document) from a Java application using the associated program installed on the computer (in this example, using MS Word or Open Office Writer).
The catch is that I want to wait until this subprocess finishes, which can be done using the waitFor() method in the Process class.
String executable = findAssociatedApplicationPath(); //for example, returns "C:\\Program Files\\Microsoft Office\\Office12\\msword.exe"
Process p = Runtime.getRuntime().exec(executable + " " + filepath);
p.waitFor();
Can someone tell me how to write the findAssociatedApplicationPath() method so it returns the correct executable? Or is there another way to do this?
The proper platform-independant way to open a file using the associated program is Desktop.open(). Unfortunately, it does not offer any way to interact with the resulting process.
If you're willing to lose platform independance, you can use the start command in cmd.exe:
String fileName = "c:\\tmp\\test.doc";
String[] commands = {"cmd", "/c", "start", "\"Title\"",fileName};
Process p = Runtime.getRuntime().exec(commands);
p.waitFor()
There's no pure Java way to do this, because it's necessarily OS-specific. On a Windows platform, the start command is probably what you're looking for (for example, start myfile.txt).
There is no "universal" way to do this across all platforms. On Windows, you can execute "start", which will find the correct associated executable. On the mac, you can execute "open". On Linux, I'm afraid you'll have to map the preferred applications manually as far as I know.
String execName = ("cmd /c \"start " + filename + "\"");
You can try to mess around with the Windows registry and other platform-specific settings, but I think the best solution is to simply have the application have its own preferences setting.
You may want to use the classes in package java.util.prefs for this.
I have figured it out.
Using the cmd.exe + start.exe combo, the method waitFor() will not wait for the subprocess to end.
If doing it without the start option it works like a charm (windows only though):
Process p = Runtime.getRuntime().exec("cmd /c \"" + filename + "\""); //extra quotes for filenames with spaces
p.waitFor()

Categories