Download an exe file and run - java

I've been trying to make it where I can download a .exe file from the web, read it, and write it to a file locally, and then execute.
URL url = new URL("http://www.ddlands.com/downloads/Calc.exe");
URLConnection c = url.openConnection();
BufferedReader br = new BufferedReader(new InputStreamReader(c.getInputStream()));
String line = "";
File file = new File("analbread"+".exe");
BufferedWriter bw = new BufferedWriter(new FileWriter(file));
while((line = br.readLine()) != null){
bw.write(line + "\n");
}
br.close();
bw.close();
Process r = Runtime.getRuntime().exec("analbread" + ".exe");
System.out.println(r.toString());
System.out.println("WORKS!");
Although I know that doesn't work due to using BufferedWriter, and i'm not sure if it runs the exe.

For the downloading part, you'll need to use binary read/write. See this for further details: Working unbuffered streams.
For the executing part, the problem is that the Runtime.exec()-method can't launch your executable file.
At least under Linux (I can't test it on Windows), you'll need the full path to the executable file (or use ./[file] when the file is in the same directory as your application) to be able to execute it.
Only giving the command works for executables which are part of your systems PATH-variable.

Have a look at ClickOnce: http://en.wikipedia.org/wiki/ClickOnce
We've used that succesfully.

Ive used the following with good results to run command line scripts. You can create a batch script that runs the executable or run it directly using the exec method - probably pass "cmd ". This opens a command prompt from which you can run anything.
public static void runScript(String batchFile, boolean waitForExit0, int retryTime)
{
try
{
String runString = "cmd /c start " + (waitForExit0?"/wait ":"") + "/MIN " + batchFile;
Process p = Runtime.getRuntime().exec(runString); // /c start /wait
while (true)
{
try
{
int exit = p.exitValue();
if (exit == 0)
{
System.out.println("completed: " + runString);
return;
}
}
catch(Exception e)
{
String s = "";
}
Thread.sleep(retryTime);
}
}
catch(Exception e)
{
String s = "";
}
}

Related

Exit(1) when running exec on java

I am running sed command in java program when i execute my java file in linux.
when i ran the command alone in linux, this will work -> sed '1d;$d' /home/sample/testdata.txt > /home/output/testupdate.txt
however when i ran my java program in linux, its returning exit(1) error . i have read through and use as an array but its still failing .
public static void main(String[] args) {
String[] cmd = {"sed", "sed '1d;$d' /home/sample/testdata.txt > /home/output/testupdate.txt"};
String s;
Process p;
try {
p = Runtime.getRuntime().exec(cmd);
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) {
}
}
Java is not a shell so does not handle redirects - your original command only works via your Linux shell which understands ">".
You can make Java launch the shell to execute the command, say if you are using bash:
String[] cmd = {"/bin/bash", "-c"
, "sed '1d;$d' /home/sample/testdata.txt > /home/output/testupdate.txt"};
Alternatively see the other helpful comments which link to other pages on dealing with the redirects within the Java code, or to do it inside Java itself (such as with Files.lines / streams).
You don’t need sed. Java can do everything sed can do.
In your case, it appears you are using sed to remove the first and last line from a file. Here’s how you would do that in Java:
Path source = Path.of("/home/sample/testdata.txt");
Path destination = Path.of("/home/output/testupdate.txt");
long lineCount;
try (Stream<?> lines = Files.lines(source)) {
lineCount = lines.count();
}
long lastLine = lineCount - 1;
try (BufferedReader in = Files.newBufferedReader(source);
BufferedReader out = Files.newBufferedWriter(destination)) {
// Skip first line
String line = in.readLine();
long counter = 0;
while ((line = in.readLine()) != null) {
if (++counter < lastLine) {
out.write(line);
out.newLine();
}
}
}
If for some reason you absolutely need to use an external process, there are many other questions and answers which cover your mistake: > is not understood by sed. Normally, it is the shell (like bash) which interprets file redirection.
The proper way to run your command would have been:
ProcessBuilder builder =
new ProcessBuilder("sed", "1d;$d", "/home/sample/testdata.txt");
builder.redirectOutput(new File("/home/output/testupdate.txt"));
builder.redirectError(ProcessBuilder.Redirect.INHERIT);
Process p = builder.start();

Executing Process in java to call external python program but program does not print anything to console

We can use Jython to implement python in java, but I dont want to go for that approach, what I am looking for is using command line utility and fire python command to execute the code and get the console output in java code.
python Main.py < input.txt
I used above command in terminal, it works there, giving me output, but unable to get the output in java code.
Note: Main.py and input.txt and java code in the same folder
What I am doing wrong in java code?
Here is Sample java code which I am calling in order to execute external python code
try {
Process process = Runtime.getRuntime()
.exec("python Main.py < input.txt");
process.waitFor();
System.out.println(process);
StringBuilder output
= new StringBuilder();
BufferedReader reader = new BufferedReader(
new InputStreamReader(process.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
output.append(line + "\n");
}
System.out.println("here");
int exitVal = process.waitFor();
if (exitVal == 0) {
System.out.println("Success!");
System.out.println(output);
} else {
System.out.println("Process failed");
}
} catch (Exception e) {
// TODO: handle exception
System.out.println(e);
}
Here is a sample python code:
x = input();
y = input();
print(type(x));
print(type(y));
print(x + y);
here is a sample input file which I am passing as a input to the python code
30
40
As sandip showed, executing a command in java is not the same as running commands through BASH.
At first I tried to execute
bash -c "python Main.py < input.txt" (through java).
For some reason this didn't work, and even if it did its not a great solution as its dependent on the system its running on.
The solution I found to work was by using ProcessBuilder to first make the command, and redirect its input to a file. This allows you to keep the python code unchanged, and for me at least, give the same result as just running the BASH command.
Example:
ProcessBuilder pb = new ProcessBuilder("python3","Main.py");
//Make sure to split up the command and the arguments, this includes options
//I only have python3 on my system, but that shouldn't affect anything
pb.redirectInput(new File("./input.txt"));
System.out.println(pb.command());
Process process = pb.start();
//The rest is the exact same as the code in the question
Heres the ProcessBuilder docs for quick reference
java process not accept < symbol to input file in python command.
Instead you can run like this
python file
f = open("input.txt", "r")
for x in f:
print(type(x));
print(x)
java file
Process process = Runtime.getRuntime().exec("python Main.py input.txt");
process.waitFor();
System.out.println(process);
StringBuilder output
= new StringBuilder();
BufferedReader reader = new BufferedReader(
new InputStreamReader(process.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
output.append(line + "\n");
}
System.out.println("here");
int exitVal = process.waitFor();
if (exitVal == 0) {
System.out.println("Success!");
System.out.println(output);
} else {
System.out.println("Process failed");
}
} catch (Exception e) {
// TODO: handle exception
System.out.println(e);
}
and use and same text file.
It should print in console

Runtime.exec command not working

I have a java application that downloads a file from a web service using wget. When executing the command through java it returns with: "wget: not an http or ftp url:"
When i execute the command directly it runs without problems. Here is my code:
try {
Debug.println("Starting copy of "+srcFile+" to "+destFile);
String command = "wget -O " + destFile + " \""+ srcFile +"\"";
Process p = Runtime.getRuntime().exec(command);
int exitCode = p.waitFor();
if(Debug.isDebugMode())
{
Debug.println(command);
BufferedReader stdInput = new BufferedReader(new InputStreamReader(p.getErrorStream()));
String s;
while((s = stdInput.readLine()) != null)
{
Debug.println(s);
}
}
Debug.println("Finished with code: " + String.valueOf(exitCode));
}
catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return false;
And this is the output:
24/04/2013 10:11:05 Starting copy of stoppenmetroken.webcolors.local/service/track?track=3b1ac68a288345c183a08c714901a398&mac=089000A09090 to /opt/byato/data/song/3b1ac68a288345c183a08c714901a398
24/04/2013 10:11:05 wget -O /opt/byato/data/song/3b1ac68a288345c183a08c714901a398 "stoppenmetroken.webcolors.local/service/track?track=3b1ac68a288345c183a08c714901a398&mac=089000A09090"
24/04/2013 10:11:05 wget: not an http or ftp url: "http://stoppenmetroken.webcolors.local/service/track?track=3b1ac68a288345c183a08c714901a398&mac=089000A09090"
24/04/2013 10:11:05 Finished with code: 1
ps: i removed the http:// part of the output because i dont have enough reputation points -.-
What am i missing?
Can you try to execute the command like this :
Process p = Runtime.getRuntime().exec("/bin/bash -c "+command); //for linux
or
Process p = Runtime.getRuntime().exec("cmd.exe /c "+command); //for Windows
Sometimes we need to explicitly invoke Linux shell or command prompt.
Hope this will work.
I suspect this:
String command = "wget -O " + destFile + " \""+ srcFile +"\"";
is the problem. When you run in a shell, the quotes around the URL will be removed. However when you run via Java you're not running via a shell and your URL starts with "http... (look closely at the error message).
If you don't want Runtime.exec() to parse and split your arguments then you might consider the variant that takes individual arguments. A more efficient solution still would be to download using HttpComponents.

Runtime.getRuntime.exec() not working for the linux command "tar -xvf filename.tar"

I am trying to untar a file on a Unix machine, using a Java batch application.
Source Code:
String fileName = "x98_dms_12";
Runtime.getRuntime().exec("gunzip "+ fileName + ".tar.gz");
System.out.println(" Gunzip:"+"gunzip "+ fileName + ".tar.gz");
Runtime.getRuntime().exec("tar -xvf "+ fileName + ".tar");
System.out.println(" Extract:tar -xvf "+ fileName + ".tar");
Problem Description:
When I run the batch program it does not (completely) work. Only the gunzip command works, converting my fileName.tar.gz to fileName.tar. But the untar command does not seem to do anything, and there is no error or exception in my log or Unix console.
When I run the same commands in a Unix prompt they work fine.
Notes:
The path of execution is correct because it converts my *.tar.gz to *.tar
I cannot use "tar -zxvf fileName.tar.gz" since the attribute "z" does not work on my system.
There is no error or exception thrown.
Please do help.
A couple of things:
The tar command will expand a file relative to your working directory, which might need to be set for your Java Process objects
You should wait for the unzip process to complete before launching into the untar process
You should process the output streams from the processes.
Here is a working example that you can extend/adapt. It uses a separate class to deal with the process output streams:
class StreamGobbler implements Runnable {
private final Process process;
public StreamGobbler(final Process process) {
super();
this.process = process;
}
#Override
public void run() {
try {
final BufferedReader reader = new BufferedReader(
new InputStreamReader(process.getInputStream()));
String line = null;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
reader.close();
} catch (final Exception e) {
e.printStackTrace();
}
}
}
public void extractTarball(final File workingDir, final String archiveName)
throws Exception {
final String gzFileName = archiveName + ".tar.gz";
final String tarFileName = archiveName + ".tar";
final ProcessBuilder builder = new ProcessBuilder();
builder.redirectErrorStream(true);
builder.directory(workingDir);
builder.command("gunzip", gzFileName);
final Process unzipProcess = builder.start();
new Thread(new StreamGobbler(unzipProcess)).start();
if (unzipProcess.waitFor() == 0) {
System.out.println("Unzip complete, now untarring");
builder.command("tar", "xvf", tarFileName);
final Process untarProcess = builder.start();
new Thread(new StreamGobbler(untarProcess)).start();
System.out.println("Finished untar process. Exit status "
+ untarProcess.waitFor());
}
}
The code below will print the output of the command executed. Check if it returns any error.
Process p = Runtime.getRuntime().exec("tar -xvf "+ fileName + ".tar");
BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = null;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
The problem is the commands which we give is UNIX command so it wont work in windows environment. I had written a script file to overcome this problem thanks all for you help. The Runtime.getRuntime.exec() will take some time to execute the command given so after each exec() give thread.wait(3000) to complete the process and goto next thread.

How to detect java process exit?

In a java program, I am generating an sh script for use on a centOS machine, which will use sox and lame to decode an MP3 audio file, then apply some gain to the file respectively. Im having some issues getting the Process.waitFor() method to do anything other than hang indefinitely. Here is the code:
try
{
// TODO code application logic here
String reviewPath = "/SomeDirectory/";
String fileName = "FileName";
String extension = ".mp3";
StringBuilder sb = new StringBuilder();
sb.append("#!/bin/bash\n");
sb.append("cd " + reviewPath + "\n");
sb.append("lame --decode " + fileName + extension + "\n");
File script = new File(reviewPath + fileName + ".sh");
script.createNewFile();
script.setExecutable(true);
FileWriter writer = new FileWriter(script);
writer.write(sb.toString());
writer.close();
Process p = Runtime.getRuntime().exec(script.getAbsolutePath());
String line;
BufferedReader bri = new BufferedReader
(new InputStreamReader(p.getInputStream()));
BufferedReader bre = new BufferedReader
(new InputStreamReader(p.getErrorStream()));
while ((line = bri.readLine()) != null) {
System.out.println(line);
}
bri.close();
while ((line = bre.readLine()) != null) {
System.out.println(line);
}
bre.close();
p.waitFor();
System.out.println("Done.");
}
catch (Exception e)
{
System.out.println(e.getMessage());
}
The odd part is that when I run the .sh file it generates by hand, it runs and exits nicely, but when I execute it from a process object in java, it never exits. The exitValue of the process is always "Process has not exited". Ive tried adding set -e to the script, and exit to the end of the script. Short of using the kill command (which I dont really think I can do here) Im at a loss as to what is going on here. Any suggestions?
Add something like while(p.getInputStream().read() != -1); after starting the process. The buffer will get filled and the process will stop waiting for something (in this case, your program) to read from it to free up space.
I figured it out! The problem here was indeed that the output streams needed to be flushed for the application to exit, but simply reading from the streams is not enough. I used Suresh Koya's suggestion and used the processBuilder api, and redirected the error stream on the process before starting it, and read from the streams. This fixed the issues I was having :D

Categories