Runtime.exec(String) limiting String - java

I'm trying to use the Java function Runetime.exec(String) to run a program in the startup folder of a windows 7 computer like so:
Runtime.getRuntime().exec(runner.getPath() + "\\run.bat");
And when I run this I get an error saying the command cannot be run:
Exception in thread "main" java.io.IOException: Cannot run program ""C:\Users\ly
ndsey\AppData\Roaming\Microsoft\Windows\Start": CreateProcess error=2, The syste
m cannot find the file specified
As you can see, the file name is cut off at the "\Windows\Start" when it should continue to "\Windows\Startup\run.bat".. Is there an alternative I can use?

Considering runner as a File instance, this should work.
Desktop.getDesktop().open(new File(runner, "run.bat"));
It uses Desktop class instead of Runtime, so you don't have to convert your File (runner) to its String representation (which is error prone). Runner is now used 'as is' as the parent directory of the "run.bat" you want to execute.
Other advantage of Desktop class : you can now open any file you want.

As an alternative you can use ProcessBuilder. I feel ProcessBuilder is more safe than Runtime.getRuntime().exec http://docs.oracle.com/javase/7/docs/api/java/lang/ProcessBuilder.html
String[] command = {"CMD", "/C", "dir"};
ProcessBuilder pb = new ProcessBuilder( command );
//set up your work directory if needed
pb.directory(new File("c:\\path"));
Process process = pb.start();

as i can see from the error you give, and i hope it's a copy past, you string runner.getPath() for some reason start and end with "\"" which make the whole path invalid. check that and remove it if needed
if you have the file already and you just need it's path you can use
runner.getAbsolutePath()
also, if runner is a file, getPath will give you the file path including the path, so your code will surely won't work. instead use:
String path = runner.getPath();
path = path.substring(0, path.lastIndexOf("\\")) + "\\run.bat";
Runtime.getRuntime().exec(path);

You should avoid the exec(String) method, which attempts to parse the entire string into command + arguments. The safe option is exec(String[]), which presupposes the first array element is the command and the rest are arguments.
So, writing
Runtime.getRuntime.exec(new String[] { yourCommandString })
is a surefire way of getting the right message across.

Related

Runtime exec cannot run programs in appdata?

I have been messing around with running some .exe files and it appears as if there is something blocking it from running it in appdata?
Runtime.getRuntime().exec(System.getenv("APPDATA") + "test.exe");
This is the error I get
java.io.IOException: Cannot run program "C:\Users\Cole": CreateProcess error=2, The system cannot find the file specified
You should not use the plain exec(String) method as it requires OS specific escaping. If you use the string array version it should find the executable.
It is also a good idea to check if the variable exists and if it ends with a \ before concatenating it with the filename. Or better use the hierachical File constructor:
String appdata = System.getenv("APPDATA");
if (appdata == null || appdata.trim().isEmpty())
appdata=".";
String fileName = new File(appdata, "test.exe").getAbsolutePath();
Runtime.getRuntime().exec(new String[]{fileName /*, noargs */});
An easy way to do this is to construct the path using a File object.
final String f = new File(System.getenv("APPDATA"), "test.exe").toString();
final Process p = Runtime.getRuntime().exec(new String[] { f });

Calling jar in my java code

I want to use a jar file Command.jar in my java code. When I run Command.jar from command line
like this java -jar Command.jar "Param1" it works well. But when I try to run it in my java code using either Process builder or Runtime.getRuntime().exec it does not work.
I tried this -
List <String> command = new ArrayList<String>();
command.add("java -jar");
command.add("Command.jar");
command.add("Param1");
ProcessBuilder builder = new ProcessBuilder(command);
try {
Process process = builder.start();
} catch (IOException e) {
}
It does not work. I also tried this:
Runtime.getRuntime().exec("java -jar Command.jar Param1");
But no luck. Please tell me where I am doing wrong
This is incorrect:
command.add("java -jar");
It should be
command.add("java");
command.add("-jar");
But there may be other problems as well. For instance java may not be accessible via the search path given by the PATH environment variable. Or Command.jar may not be in the current directory.
You need to see what (if anything) is being written by the java command to its standard output and/or standard error streams.
it does not work
does not tell us how to help you. You'll need to give us an error message or undesired result. Use System.out.println's to help you debug and narrow the problem.
From what I can guess from personal experience and other problems is that you probably ran some cd "Directory\With\Path\To\Jar" commands in command prompt when you were running it manually. You'll need to do the same for Runtime.getRuntime().exec or put the jar in the location that exec will default to in your program.
Did you try using ProcessBuilder(java.lang.ProcessBuilder)? Syntax is as follows -
ProcessBuilder pb = new ProcessBuilder("java", "-jar", "absolute path upto jar");
Process p = pb.start();
You can redirent input/output/error to/from files as follows
File commands = new File("absolute path to inputs file");
File dirOut = new File("absolute path to outputs file");
File dirErr = new File("absolute path to error file");
dirProcess.redirectInput(commands);
dirProcess.redirectOutput(dirOut);
dirProcess.redirectError(dirErr);
I have tried it and it work! Let us know any errors or exceptions you are getting.

java.io.IOException:Cannot run program "sh" (in directory"c:\cygwin\bin\test"):CreateProcess error=2.The system cannot find file specified

I am running shell scripts with the help of java and cygwin. When i am running my code in windows xp it works fine. Now i am trying to run same code on windows 7 i am getting above error.
(java.io.IOException)java.io.IOException:
Cannot run program "sh" (in directory"c:\cygwin\bin\test"):
CreateProcess error=2.The system cannot find file specified
Why this error occurred.I have set my path for cygwin (PATH=.;c:\cygwin\bin) How to avoid this.
ProcessBuilder pb = new ProcessBuilder ();
pb.directory(new File("C:\\cygwin\\bin\\Test\\"));
File shellfile = new File("app.sh");//File name with extension
System.out.println(shellfile.getCanonicalPath());
But it is giving the output as E:\NIRAJ\example\app.sh which is in my java program. even i am setting up pb.directory to the path.
if i check System.out.print(pb.directory()); it gives me output C:\cygwin\bin\Test
In PATH variable, you need to put cygwin's bin directory before any other Windows' paths.
Do this:
PATH=c:\cygwin\bin:RestWindowsPaths
Not that:
PATH=RestWindowsPathVariables:c:\cygwin\bin
First try to get the path of specified file first to ensure it:
I am not much sure but this may lead you one step ahead :
File file = new File("app.sh");//File name with extension
System.out.println(file.getCanonicalPath());
This should print : c:\cygwin\bin\test
Also use separator like this instead : c:\\cygwin\\bin\\test
Hope this helps.
UPDATE
String myCommand = "c:\\cygwin\\bin\\test\\cygbin";
String myArg = PATH_TO_shellscript+"app.sh";
ProcessBuilder p = new ProcessBuilder(myCommand, myArg).start();

How to use "cd" command using Java runtime?

I've created a standalone java application in which I'm trying to change the directory using the "cd" command in Ubuntu 10.04 terminal. I've used the following code.
String[] command = new String[]{"cd",path};
Process child = Runtime.getRuntime().exec(command, null);
But the above code gives the following error
Exception in thread "main" java.io.IOException: Cannot run program "cd": java.io.IOException: error=2, No such file or directory
Can anyone please tell me how to implement it?
There is no executable called cd, because it can't be implemented in a separate process.
The problem is that each process has its own current working directory and implementing cd as a separate process would only ever change that processes current working directory.
In a Java program you can't change your current working directory and you shouldn't need to. Simply use absolute file paths.
The one case where the current working directory matters is executing an external process (using ProcessBuilder or Runtime.exec()). In those cases you can specify the working directory to use for the newly started process explicitly (ProcessBuilder.directory() and the three-argument Runtime.exec() respectively).
Note: the current working directory can be read from the system property user.dir. You might feel tempted to set that system property. Note that doing so will lead to very bad inconsistencies, because it's not meant to be writable.
See the link below (this explains how to do it):
http://alvinalexander.com/java/edu/pj/pj010016
i.e. :
String[] cmd = { "/bin/sh", "-c", "cd /var; ls -l" };
Process p = Runtime.getRuntime().exec(cmd);
Have you explored this exec command for a java Runtime, Create a file object with the path you want to "cd" to and then input it as a third parameter for the exec method.
public Process exec(String command,
String[] envp,
File dir)
throws IOException
Executes the specified string command in a separate process with the specified environment and working directory.
This is a convenience method. An invocation of the form exec(command, envp, dir) behaves in exactly the same way as the invocation exec(cmdarray, envp, dir), where cmdarray is an array of all the tokens in command.
More precisely, the command string is broken into tokens using a StringTokenizer created by the call new StringTokenizer(command) with no further modification of the character categories. The tokens produced by the tokenizer are then placed in the new string array cmdarray, in the same order.
Parameters:
command - a specified system command.
envp - array of strings, each element of which has environment variable settings in the format name=value, or null if the subprocess should inherit the environment of the current process.
dir - the working directory of the subprocess, or null if the subprocess should inherit the working directory of the current process.
Returns:
A new Process object for managing the subprocess
Throws:
SecurityException - If a security manager exists and its checkExec method doesn't allow creation of the subprocess
IOException - If an I/O error occurs
NullPointerException - If command is null, or one of the elements of envp is null
IllegalArgumentException - If command is empty
This command works just fine
Runtime.getRuntime().exec(sh -c 'cd /path/to/dir && ProgToExecute)
Using one of the process builder's method we could pass the directory where we expect the cmd to be executed. Please see the below example. Also , you can mention the timeout for the process, using wait for method.
ProcessBuilder builder = new ProcessBuilder("cmd.exe", "/c", cmd).directory(new File(path));
Process p = builder.start();
p.waitFor(timeoutSec, TimeUnit.SECONDS);
In the above code, you can pass the file object of the path[where we expect the cmd to be executed] to the directory method of ProcessBuilder
My preferred solution for this is to pass in the directory that the Runtime process will run in. I would create a little method like follows: -
public static String cmd(File dir, String command) {
System.out.println("> " + command); // better to use e.g. Slf4j
System.out.println();
try {
Process p = Runtime.getRuntime().exec(command, null, dir);
String result = IOUtils.toString(p.getInputStream(), Charset.defaultCharset());
String error = IOUtils.toString(p.getErrorStream(), Charset.defaultCharset());
if (error != null && !error.isEmpty()) { // throw exception if error stream
throw new RuntimeException(error);
}
System.out.println(result); // better to use e.g. Slf4j
return result; // return result for optional additional processing
} catch (IOException e) {
throw new RuntimeException(e);
}
}
Note that this uses the Apache Commons IO library i.e. add to pom.xml
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.10.0</version>
</dependency>
To use the cmd method e.g.
public static void main(String[] args) throws Exception {
File dir = new File("/Users/bob/code/test-repo");
cmd(dir, "git status");
cmd(dir, "git pull");
}
This will output something like this: -
> git status
On branch main
Your branch is up to date with 'origin/master'.
nothing to commit, working tree clean
> git pull
Already up to date.
Try Use:
Runtime.getRuntime.exec("cmd /c cd path");
This worked
Runtime r = Runtime.getRuntime();
r.exec("cmd /c pdftk C:\\tmp\\trashhtml_to_pdf\\b.pdf C:\\tmp\\trashhtml_to_pdf\\a.pdf cat output C:\\tmp\\trashhtml_to_pdf\\d.pdf");
The below did not work
While using array command did NOT WORK
String[] cmd = {"cmd /c pdftk C:\\tmp\\trashhtml_to_pdf\\b.pdf C:\\tmp\\trashhtml_to_pdf\\a.pdf cat output C:\\tmp\\trashhtml_to_pdf\\d.pdf"}; r.exec(cmd);
FYI am using utility to check OS if its windows above will work for other than windows remove cmd and /c
I had solved this by having the Java application execute a sh script which was in the same directory and then in the sh script had done the "cd".
It was required that I do a "cd" to a specific directory so the target application could work properly.

Runtime class in java

How to execute a java program with the help of Runtime.getRuntime().exec().
For example we shall have the java file path as c:/java/abc.java. Please help me with the code.
Assuming that abc.java contains a main method that you want to execute:
Runtime.getRuntime().exec("javac c:\java\abc.java -d c:\java\")
Runtime.getRuntime().exec("java c:\java\abc")
Do not forget that:
you may need to read stdout/stderr of a java program
you may have to set/update environment variable and PATH before executing your java command
CreateProcess: c:\j2sdk1.4.0\bin\helloworld error=2
means Win32's CreateProcess returns a 2 as error code when it cannot find the command you specify; more specifically, when the command does not refer to an executable file on its lookup path.
Look at this SO question for a more complete "Runtime.getRuntime().exec()" code, and also to this snippet.
This code creates a shell (as in Runtime.getRuntime().exec("cmd /K")), in which you write on sdtin whatever command you want to execute.
The interest of this approach is to reuse the shell process to benefit from a previous command: it you execute a 'cd', then execute a 'dir', the latter command would display the content of the directory referenced by the cd command.
The same would be true for PATH settings, just before using javac or java.
You should use ProcessBuilder instead of Runtime. Basic usage is like:
Process process = new ProcessBuilder(command).start();
You will find more code under the link above. Also see this question.
You mean you want a Java program to run another Java program. This SO thread might be helpful, in that case.
String path1 = "f://" + File.separator+username+File.separator+progName;
Runtime runtime = Runtime.getRuntime();
String command = "javac -classpath " + path + " " + path1;
System.out.println(command);
Process process = runtime.exec(command);
InputStream error = process.getErrorStream();
Please see the excellent resource which used to be called javaalmanac.
http://www.exampledepot.com/egs/java.lang/Exec.html
try {
// Execute a command with an argument that contains a space
String[] commands = new String[]{"grep", "hello world", "/tmp/f.txt"};
commands = new String[]{"grep", "hello world", "c:\\Documents and Settings\\f.txt"};
Process child = Runtime.getRuntime().exec(commands);
} catch (IOException e) {
}

Categories

Resources