Java - executing external exe file - java

I have a executable program made on C++ (cf.exe) that takes parameters from a few text files (.txt), performs some calculations, and creates a file with the results (results.txt). This program needs no interaction. Once executed, when the calculations are done, it's automatically closed.
Then, I have other program made on Java, which contains a button that executes the cf.exe. When the button is pressed the following method is called:
public void executeExternalProgram(){
String filePath = "C++" + File.separator + "cf.exe";
try {
System.out.println("Executing C++ exe...");
Process p = Runtime.getRuntime().exec(filePath);;
} catch (Exception e) {
e.printStackTrace();
}
}
I don't get any error, but the cf.exe is not being executed when I press the button. When I execute manually the cf.exe, the results file is correctly created. Furthermore, I've tried to copy other programs, such as notepad.exe, to the same folder and execute it through Java without any problem. Can anyone see why it's not working?

I found that changing the command given to the process makes it work correctly. The change is the following:
Process p = Runtime.getRuntime().exec("cmd /c start "+ filePath);
Then, the updated code for the method called when the button is pushed:
public void executeExternalProgram(){
String filePath = "C++" + File.separator + "cf.exe";
try {
System.out.println("Executing C++ exe...");
Process p = Runtime.getRuntime().exec("cmd /c start "+ filePath);
} catch (Exception e) {
e.printStackTrace();
}
}

Related

Java CommandBuilder incomplete execution of copy command

I built a web crawler that records a livestream. After the recording is finished, the individual *.ts files are to be merged into a video. Since after my research FFMPEG has only a complex procedure over a text file as input parameter, it seems to me clearly eifnacher to use the available functions of the operating system.
I can use cmd.exe /c copy /b *.ts J:\final\output.mp4
to merge my ts files. However, as soon as I execute the command via the CommandBuilder, only the first 5 to 10 files are merged. So the video will be only a few seconds long. If I execute the command manually via Windows, all files are merged correctly. How does this happen? My commandExecture method looks like this:
private int execCommand(String dirPath, String command) {
try {
String[] commandArr = command.split(" ");
ProcessBuilder pb = new ProcessBuilder(commandArr);
pb.directory(new File(dirPath));
pb. redirectErrorStream(true);
Process p = pb.start();
return p.exitValue();
} catch (IOException e) {
e.printStackTrace();
}
return -9999;
}
I suspected that the program exited before the command was fully executed. So I added the following after pb.start() :
while(p.isAlive()) {
try {
Thread.sleep(500);
System.out.println("running");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
also this did not change anything. How does this happen and how can I make it merge automatically?

Java Fails to Run Large Python Files

I have a Python script which I am attempting to run via code in Java.
The Python script runs fine when run through a Linux terminal command on my Ubuntu virtual machine using an identical command to the one being passed through the Java script.
The Java code runs fine when running a different Python script that runs faster than the Python script I'm attempting to run..
However, despite both the Python script running fine and the Java script running fine, somehow, when I put the two together, nothing happens: The .txt file isn't updated, so the Java script prints out whatever old value it contains.
System.out.println("starting...");
try {
Process process = Runtime.getRuntime().exec("python3 /home/.../PycharmProjects/.../fraudanalysis.py abc def");
Thread.sleep(900000);
# Or try System.out.println(process.waitFor());
File file = new File("/home/.../PycharmProjects/.../output.txt");
Scanner newLineReader = new Scanner(file);
System.out.println(newLineReader.nextLine());
} catch(Exception e) {
System.out.println(e);
}
The code above should run the Python3 script at the absolute directory provided, using two arguments. The Python3 script completes after around 13 minutes and updates the output.txt file, which is then read by the Java program after waiting 15 minutes (or you can tell the thread to wait for completion-- process.WaitFor() returns 1).
def testScript():
time.sleep(780)
return_string1 = sys.argv[1]
return_string2 = sys.argv[2]
outputFile = open(os.path.dirname(os.path.abspath(__file__)) + "/output/output.txt", "w+")
outputFile.write(return_string1 + " " + return_string2)
print("Python run complete")
if __name__ == "__main__":
testScript()
The script above is a good stand-in for the Python script. If you lower the sleep time to 10 minutes for the Python script, it runs when Java sends the command. But, at the sleep times shown above, Java apparently fails to run the script, or the script run attempt ends in failure.
Additional info: the Java command is activated using a JavaFX button. The Java script has been developed in IntelliJ IDEA and the Python script was created using PyCharm.
My question is, what are possible causes for this problem, when both scripts work fine on their own?
As a simple suggestion, you should not rely on Thread.sleep method with a fixed parameter such as 15 minutes. Your data may grow or shrink and that way of proceeding is not efficient.
You could try to call the Process.waitFor() method so that when the python process is over, your thread continues.
Moreover, you could try to use ProcessBuilder that sometimes helps when facing buggy System exec cases.
Here is some code. in sub(), you can not change the python program, but for sub2() to work, you have to modify the python program so that its output is on the standard out and Java would do the redirect to the output.txt file.
public void sub() {
System.out.println("startig...");
Scanner newLineReader = null;
try {
Process process = Runtime.getRuntime().exec("python3 /home/.../PycharmProjects/.../fraudanalysis.py /home/.../PycharmProjects/.../fraudAnalysis.db 500");
process.waitFor();
File file = new File("/home/.../PycharmProjects/.../output.txt");
newLineReader = new Scanner(file);
String line;
while((line=newLineReader.nextLine())!=null) {
System.out.println(line);
}
} catch(IOException ioe) {
ioe.printStackTrace();
}catch(InterruptedException ie) {
ie.printStackTrace();
}finally {
newLineReader.close();
}
}
public void sub2() {
ProcessBuilder pb =
new ProcessBuilder("python3",
"/home/.../PycharmProjects/.../fraudanalysis.py",
"/home/.../PycharmProjects/.../fraudAnalysis.db", "500");
File log = new File("/home/.../PycharmProjects/.../output.txt");
pb.redirectErrorStream(true);
pb.redirectOutput(Redirect.appendTo(log));
Process p = null;
try {
p = pb.start();
} catch (IOException e) {
e.printStackTrace();
}
try {
p.waitFor();
} catch (InterruptedException e) {
e.printStackTrace();
}
Scanner newLineReader = null;
try{
newLineReader = new Scanner(log);
String line;
while((line=newLineReader.nextLine())!=null) {
System.out.println(line);
}
}catch(IOException ioe) {
ioe.printStackTrace();
}
}
I was able to get it to work with a small modification. I used relative file locations and TimeUnit.MINUTES.sleep(15);
package org.openjfx;
import java.io.File;
import java.util.Scanner;
import java.util.concurrent.TimeUnit;
public class TestWait {
public static void main(String[] args) {
System.out.println("starting...");
String dir="src/main/resources/org/openjfx/";//location of the python script
try {
System.out.println("Working Directory = " + System.getProperty("user.dir"));
//System.out.println("python3 " + dir+"fraudanalysis.py abc def");
Process process = Runtime.getRuntime().exec("python3 " + dir+"fraudanalysis.py abc def");
System.out.println(process.waitFor());
TimeUnit.MINUTES.sleep(15);
File file = new File("src/main/resources/org/openjfx/output.txt");
Scanner newLineReader = new Scanner(file);
System.out.println(newLineReader.nextLine());
} catch (Exception e) {
System.out.println(e);
}
}
}
Here is the python I used.
import sys
import time
def testScript():
return_string1 = sys.argv[1]
return_string2 = sys.argv[2]
time.sleep(780)
outputFile = open("src/main/resources/org/openjfx/output.txt", "w+")
outputFile.write(return_string1 + " " + return_string2)
print("Python run complete")
if __name__ == "__main__":
testScript()
it's a timeout error. can't be fixed. just pick between Java and Python and write everything in it. no reason to use both.

Trying to run a command-line driven C++ Project in Java

I have a c++ program (.exe) that runs in the command line. You don't open it with cmd, it just opens the command prompt on its own and uses it as a menu. I also have a login system built in Java. My issue is, I'm trying to open my C++ program in the Java program, and it just isn't working. Here is the latest iteration of the relevant code:
btnLaunchMyProgram.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
File file1 = new File("C://Users//" + System.getProperty("user.name") + "//Desktop//My Program//myprogram.exe");
if(!file1.exists()) {
try {
HttpDownloadUtility.downloadFile("https://www.example.com/downloads/MyProgram.exe", "C://Users//" + System.getProperty("user.name") + "//Desktop//My Program//");
} catch (IOException e) {
e.printStackTrace();
}
}
try {
Process p = Runtime.getRuntime().exec(new String[] {"cmd.exe", "\"" + "C://Users//" + System.getProperty("user.name") + "//Desktop//My Program//MyProgram.exe" + "\""});
} catch (IOException e) {
e.printStackTrace();
}
}
});
In order to get rid of a few concerns you might have
- I have also tried the following, which runs my program in the background, but doesn't open the command prompt:
Process p = Runtime.getRuntime().exec(new String[] {"C://Users//" + System.getProperty("user.name") + "//Desktop//My Program//MyProgram.exe"});
and also:
Process p = Runtime.getRuntime().exec(new String[] {"cmd.exe", "C://Users//" + System.getProperty("user.name") + "//Desktop//My Program//MyProgram.exe"});
None of these work.
Just to be clear about what I need to happen:
1. I press the button (btnLaunchMyProgram)
2. It opens the exe and, by extension, the command prompt / console.
3. That's basically all it needs to do.

Setting Linux ACL permissions using Java Process

I am attempting to change the ACL permissions active on certain files using a result from an API I have built.
executorService.scheduleAtFixedRate(new Runnable() {
public void run() {
System.out.println("hello");
JSONArray data = ServerAPI.riskCheck();
if(data != null){
JSONArray policycontent = data;
for(int i = 0; i < policycontent.length(); i++){
JSONObject privilege = policycontent.getJSONObject(i);
String user = privilege.getString("user");
String filepath = privilege.getString("filePath");
String accesses = "";
if(privilege.getBoolean("read") == true){
accesses = accesses + "r";
}
if(privilege.getBoolean("write") == true){
accesses = accesses + "w";
}
if(privilege.getBoolean("execute") == true){
accesses = accesses + "x";
}
if(privilege.getBoolean("execute") == false && privilege.getBoolean("write") == false && privilege.getBoolean("read") == false){
accesses = "-";
}
try {
System.out.println("TRYING TO RUN:");
Process p = Runtime.getRuntime().exec("setfacl -m \"u:" + user + ":" + accesses + "\" " + filepath);
//p.waitFor();
int exitVal = p.waitFor();
System.out.println("Exited with error code "+exitVal);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//System.out.println("setfacl -m \"u:" + user + ":" + accesses + "\" " + filepath);
}
}
System.out.println(ServerAPI.getRiskValue());
}
},1, 1, TimeUnit.SECONDS);
}
The query to the API is done every 1 second currently, checking as soon as a "risk value" is changed, it will get new permissions.
I am running this as a JAR in the folder with the files upon which the permissions should be enacted.
I am running the JAR as root.
I have attempted to do something as simple as append a line to a file in the same directory as the JAR on each iteration of the loop, however it does not do anything.
Each of the commands is a valid command that works when I run it in the terminal manually. The System.out.println was used to ensure that the command is being interpreted correctly, but seeing as it didn't matter what command I tried, I am running out of ideas.
It also exits with status 0 each time, and I have not been able to debug despite also trying to use processbuilder and variants of that approach, including error outputs.
Is this simply something I can not do using a Java program?
Thanks in advance!
The usual source of this sort of the problem is that Runtime.exec() does not provide a shell. If you want to execute commands in a shell, you'll need to actually execute a shell.
A possible work-around is to create bash shell script containing the commands that you want to run. Put #!/usr/bin/env bash at the top of the script to make sure that it gets run by the bash shell.
Then you can exec() the script, and pass it any arguments that you need to.
Edit - I've done this in the past by creating a single shell script as part of the application installation, not creating it dynamically. If you only need to do one thing, and can parameterize the script, this works well.

File can not be executed from Java

When i try this code, it seems as executed but it is not executed.
The process builder can find the executable file. System writes the println commands.
I found some example codes but my executable file is not in same folder with java file.
private static void executeOneFile(String folderPath) {
Process p;
String exePath = path + "\\" + folderPath + "\\";
try {
p = new ProcessBuilder(exePath + "myFile.exe").start();
//p = Runtime.getRuntime().exec("myFile.exe", null , new File(exePath) );
System.out.println("p is running");
p.waitFor();
System.out.println("p ended");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
There are several problems with the code above:
You don't handle stdin/stdout properly. So maybe there is an error but you won't see it because you're not reading the output of the child process.
Next, it's always a good idea to close the child's stdin with p.getOutputStream().close() to make sure it doesn't hang waiting for input.
Lastly, the current directory of the process is the same as that of the Java VM. So if you use relative paths to write the file, it will end up somewhere but rarely where you expect. Pass the absolute path of the file to your child process to make sure the output goes where it should.

Categories