I am trying to create a disk space from Java code using qemu-img so I instantiated process and runtime classes. When run the program the command is not executed though I used the same mechanism for similar execution and it work fine. So I am wondering whether I miss something here.
StringBuilder commandBuilder = new StringBuilder("qemu-img create -f "+chosenStorageType+" ~/"+storageName+".img "+storageSize+"M");
System.out.println(commandBuilder);
String command = commandBuilder.toString();
System.out.println("this is the correct one: "+command);
System.out.println("Creating the image...");
Runtime runtime = Runtime.getRuntime();
Process process = null;
try {
process = runtime.exec(command);
System.out.println("from process try..catch");
} catch (IOException e1) {
e1.printStackTrace();
System.out.println(e1.getMessage());
}finally{
System.out.println("from finally entry");
process.destroy();
}
the output is as following:
qemu-img create -f raw ~/testSPACE.img 23.0M
this is the correct one: /qemu-img create -f raw ~/testSPACE.img 23.0M
Creating the image...
from process try..catch
from finally entry
But if I go to the directory the file isn't created.
Just to test it if I copy the output into terminal everything works like a charm.
The tilde (~) here
" ~/"+storageName+".img "
is interpreted by the shell as meaning your home directory. I would substitute the real path.
Note also that you need to be consuming the process stdout/err, and collecting the error code of the process (and checking it!) via Process.waitFor()
Related
I am trying to write a variable to ~/.bash_profile using commands like echo, but I am unable to write it to the file.
I tried the following,
Runtime run = Runtime.getRuntime();
String line = null;
try {
Process pr = run.exec("echo \"export ANDROID_HOME=/Users/abc/Documents/platform-tool\" >> ~/.bash_profile");
pr.waitFor();
BufferedReader buf = new BufferedReader(new InputStreamReader(pr.getInputStream()));
while ((line = buf.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
logger.error("Error occurred when getting adb " + e.getMessage());
} catch (InterruptedException ie) {
logger.error("Error occurred when getting adb " + ie.getMessage());
Thread.currentThread().interrupt();
}
I also tried giving ' instead of \" and just echo export still it is not writing to that file.
When I try to print the output it prints
"export ANDROID_HOME=/Users/abc/Documents/platform-tool" >> ~/.bash_profile
But the file is empty.
I also tried using printf but that again does not work. Also these commands do work in terminal but using in java, it is not writing to the file.
Any help would be appreciated and if there are other methods than which I'm using please suggest
When you do echo foo >> bar in Terminal, there are two important differences:
echo is an built-in bash command (as opposed to /bin/bash that can be found in PATH) - but that's not very important, since the two behave the same; and
>> is processed by bash and not given to echo as a parameter to print. It is bash that handles parsing the command line, handling redirection, and a bunch of other things like handling variable substitution. In this case, Java parses the command line, and hands them directly to the program.
So in essence, you're executing:
'/bin/echo' '"export ANDROID_HOME=/Users/abc/Documents/platform-tool\"' '>>' '~/.bash_profile'
If you try that in Terminal, it will do the same thing your Java-invoked echo did.
In order to do what you want, you would need to run a shell (e.g. bash) to handle the redirection:
run.exec("bash -c 'echo \"export ANDROID_HOME=/Users/abc/Documents/platform-tool\" >> ~/.bash_profile'")
However, a natural question to pose here is - why use Java to invoke bash to call echo...? Why not just use Java? (How to append text to an existing file in Java)
In my Java application, I want to run a batch file that calls "scons -Q implicit-deps-changed build\file_load_type export\file_load_type"
It seems that I can't even get my batch file to execute. I'm out of ideas.
This is what I have in Java:
Runtime.
getRuntime().
exec("build.bat", null, new File("."));
Previously, I had a Python Sconscript file that I wanted to run but since that didn't work I decided I would call the script via a batch file but that method has not been successful as of yet.
Batch files are not an executable. They need an application to run them (i.e. cmd).
On UNIX, the script file has shebang (#!) at the start of a file to specify the program that executes it. Double-clicking in Windows is performed by Windows Explorer. CreateProcess does not know anything about that.
Runtime.
getRuntime().
exec("cmd /c start \"\" build.bat");
Note: With the start \"\" command, a separate command window will be opened with a blank title and any output from the batch file will be displayed there. It should also work with just `cmd /c build.bat", in which case the output can be read from the sub-process in Java if desired.
Sometimes the thread execution process time is higher than JVM thread waiting process time, it use to happen when the process you're invoking takes some time to be processed, use the waitFor() command as follows:
try{
Process p = Runtime.getRuntime().exec("file location here, don't forget using / instead of \\ to make it interoperable");
p.waitFor();
}catch( IOException ex ){
//Validate the case the file can't be accesed (not enought permissions)
}catch( InterruptedException ex ){
//Validate the case the process is being stopped by some external situation
}
This way the JVM will stop until the process you're invoking is done before it continue with the thread execution stack.
Runtime runtime = Runtime.getRuntime();
try {
Process p1 = runtime.exec("cmd /c start D:\\temp\\a.bat");
InputStream is = p1.getInputStream();
int i = 0;
while( (i = is.read() ) != -1) {
System.out.print((char)i);
}
} catch(IOException ioException) {
System.out.println(ioException.getMessage() );
}
ProcessBuilder is the Java 5/6 way to run external processes.
To run batch files using java if that's you're talking about...
String path="cmd /c start d:\\sample\\sample.bat";
Runtime rn=Runtime.getRuntime();
Process pr=rn.exec(path);`
This should do it.
The executable used to run batch scripts is cmd.exe which uses the /c flag to specify the name of the batch file to run:
Runtime.getRuntime().exec(new String[]{"cmd.exe", "/c", "build.bat"});
Theoretically you should also be able to run Scons in this manner, though I haven't tested this:
Runtime.getRuntime().exec(new String[]{"scons", "-Q", "implicit-deps-changed", "build\file_load_type", "export\file_load_type"});
EDIT: Amara, you say that this isn't working. The error you listed is the error you'd get when running Java from a Cygwin terminal on a Windows box; is this what you're doing? The problem with that is that Windows and Cygwin have different paths, so the Windows version of Java won't find the scons executable on your Cygwin path. I can explain further if this turns out to be your problem.
Process p = Runtime.getRuntime().exec(
new String[]{"cmd", "/C", "orgreg.bat"},
null,
new File("D://TEST//home//libs//"));
tested with jdk1.5 and jdk1.6
This was working fine for me, hope it helps others too.
to get this i have struggled more days. :(
I had the same issue. However sometimes CMD failed to run my files.
That's why i create a temp.bat on my desktop, next this temp.bat is going to run my file, and next the temp file is going to be deleted.
I know this is a bigger code, however worked for me in 100% when even Runtime.getRuntime().exec() failed.
// creating a string for the Userprofile (either C:\Admin or whatever)
String userprofile = System.getenv("USERPROFILE");
BufferedWriter writer = null;
try {
//create a temporary file
File logFile = new File(userprofile+"\\Desktop\\temp.bat");
writer = new BufferedWriter(new FileWriter(logFile));
// Here comes the lines for the batch file!
// First line is #echo off
// Next line is the directory of our file
// Then we open our file in that directory and exit the cmd
// To seperate each line, please use \r\n
writer.write("cd %ProgramFiles(x86)%\\SOME_FOLDER \r\nstart xyz.bat \r\nexit");
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
// Close the writer regardless of what happens...
writer.close();
} catch (Exception e) {
}
}
// running our temp.bat file
Runtime rt = Runtime.getRuntime();
try {
Process pr = rt.exec("cmd /c start \"\" \""+userprofile+"\\Desktop\\temp.bat" );
pr.getOutputStream().close();
} catch (IOException ex) {
Logger.getLogger(MainFrame.class.getName()).log(Level.SEVERE, null, ex);
}
// deleting our temp file
File databl = new File(userprofile+"\\Desktop\\temp.bat");
databl.delete();
The following is working fine:
String path="cmd /c start d:\\sample\\sample.bat";
Runtime rn=Runtime.getRuntime();
Process pr=rn.exec(path);
This code will execute two commands.bat that exist in the path C:/folders/folder.
Runtime.getRuntime().exec("cd C:/folders/folder & call commands.bat");
import java.io.IOException;
public class TestBatch {
public static void main(String[] args) {
{
try {
String[] command = {"cmd.exe", "/C", "Start", "C:\\temp\\runtest.bat"};
Process p = Runtime.getRuntime().exec(command);
} catch (IOException ex) {
}
}
}
}
To expand on #Isha's anwser you could just do the following to get the returned output (post-facto not in rea-ltime) of the script that was run:
try {
Process process = Runtime.getRuntime().exec("cmd /c start D:\\temp\\a.bat");
System.out.println(process.getText());
} catch(IOException e) {
e.printStackTrace();
}
I am trying to use java to run a batch file at an absolute location. The batch file will compile a couple of java files.
Here is the code which I have been trying:
String s=file.getAbsolutePath() + "\\compile.bat";
Runtime rut = Runtime.getRuntime();
try {
rut.exec(new String[] {file.getAbsolutePath() + "\\compile.bat"});
}catch(IOException e1) {
e1.printStackTrace();
}
System.out.println(s);
Now, when this code gets executed, I get no console errors, but the batch file is not run. When I run the batch file through Windows Explorer, however, the batch file works, compiles the files and closes when done.
How do you know that there were no console errors?
Try this:
String s=file.getAbsolutePath() + "\\compile.bat";
Runtime rut = Runtime.getRuntime();
try {
Process process = rut.exec(new String[] {file.getAbsolutePath() + "\\compile.bat"});
// prints out any message that are usually displayed in the console
Scanner scanner = new Scanner(process.getInputStream());
while (scanner.hasNext()) {
System.out.println(scanner.nextLine());
}
}catch(IOException e1) {
e1.printStackTrace();
}
System.out.println(s);
Check the return value of the subprocess using exitValue().
Also read the error stream getErrorStream() if the exist value is non zero.
Note that when using your invocation of Runtime.exec, the working directory of the command being executed will be the current working directory of the java process. Does your batch file need to run in a specific directory?
If you need to set a specific working directory for the sub-process, you'll need to use another version of Runtime.exec.
I currently have a java program that uses xcopy with Runtime.exec to copy files. But the problem now is that when the file name has chinese characters this does not work.
It gives a file not found error.
However if i copy the file path from explorer and do xcopy from the command line copy works.
I am executing it from a Windows 7 machine. Any solutions will be much appreciated.
Thanks
This is related to the bug http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4947220. Instead of passing the parameters as arguments, passed them via environment variables which worked perfectly.
Why are you using xcopy? Use java.
Try to do it with java.nio.file.Files
Path a = ...
Path b = ...
Files.copy(a,b);
See here for doc:
http://docs.oracle.com/javase/7/docs/api/java/nio/file/Files.html#copy(java.nio.file.Path,%20java.nio.file.Path,%20java.nio.file.CopyOption...)
The exec in Java converts the strings to the system code page.
Shameful, for the XXI century, but that's how it is.
But Java is not the only bottleneck here. The console is also problematic, and xcopy might have it's own share.
There is a lot of voodoo that you can try, for instance starting cmd.exe as Unicode (/U), and/or setting the code page to utf-8 (chcp 65001), or create a batch file with the command and call that batch (so no high-ascii in the exec function).
But I would not relay on that.
Since everything is Windows only anyway, I would probably try using jni to implement a "proper" exec, or see if FileCopy is faster than the Java copy.
If you need to copy large files, or files and all the system permissions associated with a file, using java internal File.copy() will be too expensive, so you can offload all the load to your system.
Try the following trick - first, user string array as an argument to exec(); second, execute your 'xcopy' in a pipe after 'cmd' command with /C argument. Look at the sample code near line where I make isWindows() call.
The trick is that your xcopy command will be executed inside CMD shell, and /C will terminate it after successful execution. More aboutCMD.exe.
public int sysCopyFile(Resource fromResource, Resource toResource) throws ServiceException {
int returnCode = -1;
try {
String[] copyCommand = null;
if ( IOUtils.isWindows() ) {
copyCommand = new String[] {"cmd", "/C", "copy", "/Y", fromResource.getFile().getAbsolutePath(), toResource.getFile().getAbsolutePath()};
} else if ( IOUtils.isUnix() || IOUtils.isMac() ) {
copyCommand = new String[] {"/bin/cp", "-pr", fromResource.getFile().getAbsolutePath(),toResource.getFile().getAbsolutePath()};
}
final Process p = Runtime.getRuntime().exec(copyCommand);
new StreamLogger(p.getErrorStream(), log, StreamLogger.WARN);
new StreamLogger(p.getInputStream(), log, StreamLogger.DEBUG);
returnCode = p.waitFor();
if (returnCode != 0) throw new ServiceException("Unable to to copy. Command: {" + copyCommand[0] + "} has returned non-zero returnCode: " + returnCode);
} catch (IOException e) {
throw new ServiceException(e);
} catch (InterruptedException e) {
throw new ServiceException(e);
}
return returnCode;
}
I want to open Notepad in my Java program. Suppose that I have one button if I click this button the notepad will appear.
I already have a file name and a directory.
How can I implement this case?
Try
if (Desktop.isDesktopSupported()) {
Desktop.getDesktop().edit(file);
} else {
// I don't know, up to you to handle this
}
Make sure the file exists. Thanks to Andreas_D who pointed this out.
(assuming you want notepad to open "myfile.txt" :)
ProcessBuilder pb = new ProcessBuilder("Notepad.exe", "myfile.txt");
pb.start();
Assuming you wish to launch the windows program notepad.exe, you are looking for the exec function. You probably want to call something like:
Runtime runtime = Runtime.getRuntime();
Process process = runtime.exec("C:\\path\\to\\notepad.exe C:\\path\\to\\file.txt");
For example, on my machine notepad is located at C:\Windows\notepad.exe:
Runtime runtime = Runtime.getRuntime();
Process process = runtime.exec("C:\\Windows\\notepad.exe C:\\test.txt");
This will open notepad with the file test.txt open for editing.
Note you can also specify a third parameter to exec which is the working directory to execute from - therefore, you could launch a text file that is stored relative to the working directory of your program.
Using SWT, you can launch any
If you want to emulate double-clicking on a text in windows, it's not possible only with a plain JRE. You can use a native library like SWT and use the following code to open a file:
org.eclipse.swt.program.Program.launch("c:\path\to\file.txt")
If you don't want to use a third-party lib, you should know and you know where notepad.exe is (or it's visible in PATH):
runtime.exec("notepad.exe c:\path\to\file.txt");
Apache common-exec is a good library for handling external process execution.
UPDATE: A more complete answer to your question can be found here
In IDE (Eclipse) it compains about "C:\path\to\notepad.exe C:\path\to\file.txt" .
So i have used the following which works for me keeping me and my IDE happy :o)
Hopefully this will help others out there.
String fpath;
fPath =System.getProperty("java.io.tmpdir")+"filename1" +getDateTime()+".txt";
//SA - Below launches the generated file, via explorer then delete the file "fPath"
try {
Runtime runtime = Runtime.getRuntime();
Process process = runtime.exec("explorer " + fPath);
Thread.sleep(500); //lets give the OS some time to open the file before deleting
boolean success = (new File(fPath)).delete();
if (!success) {
System.out.println("failed to delete file :"+fPath);
// Deletion failed
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
String fileName = "C:\\Users\\Riyasam\\Documents\\NetBeansProjects\\Student Project\\src\\studentproject\\resources\\RealWorld.chm";
String[] commands = {"cmd", "/c", fileName};
try {
Runtime.getRuntime().exec(commands);
//Runtime.getRuntime().exec("C:\\Users\\Riyasam\\Documents\\NetBeansProjects\\SwingTest\\src\\Test\\RealWorld.chm");
} catch (Exception ex) {
ex.printStackTrace();
}
You could do this the best if you start notepad in command line with command: start notepad
String[] startNotePadWithoutAdminPermissions = new String[] {"CMD.EXE", "/C", "start" "notepad" };
Save array of string commands and give it like parametr in exec
Process runtimeProcess = Runtime.getRuntime().exec(startNotepadAdmin2);
runtimeProcess.waitFor();