Using gcc directly with ProcessBuilder creates no output files - java

I'm trying to compile C source file with gcc using ProcessBuilder. I managed to make it running but there is no output file.
Here is my code (based on this answer) :
public void compileWithGccNoCmd(Path sourcePath) throws IOException {
String sourcePathString = sourcePath.toString();
String outputPathString = sourcePath.getParent().toString() + "\\" + Files.getNameWithoutExtension(sourcePath.toString());
try {
ProcessBuilder pb = new ProcessBuilder("gcc", "-fprofile-arcs -ftest-coverage -o " + outputPathString, sourcePathString);
pb.directory(sourcePath.getParent().toFile()); // this was added later
Process compile = pb.start();
compile.waitFor();
if (compile.exitValue() == -1) {
// if error
System.out.print("COMPILE ERROR");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
My first thought that it has something to do with the working directory so I add pb.directory() but the output file still not there.
Since I can't find any solution to this, I tried another way by running gcc with cmd. I set the working directory to make sure the output files on the right place. This is the alternative code (based on this answer):
public void compileWithGcc(Path sourcePath) throws IOException {
String sourcePathString = sourcePath.toString();
String outputPathString = sourcePath.getParent().toString() + "\\" + Files.getNameWithoutExtension(sourcePath.toString());
ProcessBuilder pb;
try {
pb = new ProcessBuilder("cmd", "/C", "gcc " + sourcePathString + " -o " + outputPathString + " -fprofile-arcs -ftest-coverage");
pb.directory(sourcePath.getParent().toFile());
Process p = pb.start();
p.waitFor();
int x = p.exitValue();
} catch (Exception ex) {
ex.printStackTrace();
}
}
For some reason it works! Why is this happened? I'm pretty sure both is running gcc with the same parameter

This line:
ProcessBuilder pb = new ProcessBuilder("gcc", "-fprofile-arcs -ftest-coverage -o " + outputPathString, sourcePathString)
needs to look like this:
ProcessBuilder pb = new ProcessBuilder("gcc", "-fprofile-arcs", "-ftest-coverage", "-o", outputPathString, sourcePathString)
What you are doing with the first line is passing two arguments to gcc, one of which is "-fprofile-arcs -ftest-coverage -o " + outputPathString, instead of passing the five arguments of my edited line. gcc won't understand that.
When you use cmd like you did, it parses the command that you gave it and passes the arguments correctly, that's why it works.

Related

How to run jhipster command from a java program

I'm trying to run the jhipster import-jdl command from a java program as show below.
public boolean generate(String foldername, String filename) {
Runtime rt = Runtime.getRuntime();
try {
IPath root = ResourcesPlugin.getWorkspace().getRoot().getLocation();
Process proc = rt.exec(new String[] { "cmd", "/K",
"cd " + root + "\\" + foldername + " && jhipster import-jdl " + filename });
}
catch (IOException e) {
e.printStackTrace();
}
return true;
}
But the entity files are not getting created.
But if I open the command prompt in the folder specified in the code and run the same command as shown below manually, the entity files are generated.
cd C:\GitClone\work && jhipster import-jdl swaggertest.jh
I'm new to these things and have no idea on where am I going wrong. Please help me with the same.

-javaagent: option recognised as a command

In an application I am writing, I need to use the javaagent option to call an external jar in the same folder as my current jar file. When I run the code from the jar file, I get told: "Error: Could not find or load main class -javaagent:" but when I am running it from a batch file, it works as excepted.
I am using a ProcessBuilder to start the application:
String java = System.getProperty("java.home") + File.separatorChar + "bin" + File.separatorChar +"java.exe";
File transagent = new File(pluginDir + File.separatorChar + "TransAgent.jar");
String doublequote = String.valueOf('"');
List<String> commandlist = new ArrayList<String>();
commandlist.add(java);
commandlist.add(" -javaagent:");
commandlist.add(doublequote);
commandlist.add(transagent.getAbsolutePath());
commandlist.add(doublequote);
for(int i = 0; i < commandlist.size(); i++){
String part = commandlist.get(i);
System.out.print(part);
}
System.out.println();
ProcessBuilder pb = new ProcessBuilder();
pb.command(commandlist);
pb.redirectError(Redirect.appendTo(errorfile));
pb.redirectOutput(Redirect.appendTo(logfile));
try {
pb.start();
} catch (IOException e) {
e.printStackTrace();
}
But, when I go to the error file, I see "Error: Could not find or load main class -javaagent:"
This would usually be thrown if the option isn't valid, but I've checked the dash to work file. And I put what printed from the application in a batch file, and it worked fine. Why?
You can try this code below:
ProcessBuilder pb = new ProcessBuilder("java", "-javaagent:"+transagent.getAbsolutePath(), "YouMainClass");
pb.redirectError(Redirect.appendTo(errorfile));
pb.redirectOutput(Redirect.appendTo(logfile));
try
{
pb.start();
}
catch(IOException e)
{
e.printStackTrace();
}

How to handle spaces in path to a windows batch file?

I have a batch file on windows machine.
The path to the same is having spaces in it. E.g. C:\Hello World\MyFile.bat
I am trying to execute the batch file through java as:
Runtime.getRuntime().exec(dosCommand + destinationFilePath + batch)
But, as the path has spaces, it says "C:\Hello" is not a valid command or directory.
I tried this too:
Complete command: cmd /c start /wait "C:/Hello World/MyFile.bat" It opens the command prompt, but does not go to the folder Hello World and does not execute the bat file
How do I handle this situation.
Let me know if any additional Info. is required.
Using quotation marks ("C:\Hello World\MyFile.bat") should do the trick. Within Java you'll have to secape the quotation marks with \ (String batch = "\"C:\Hello World\MyFile.bat\"").
I was able to solve it using ProcessBuilder.
The directory in which the bat file is present can be added to the working directory as:
processBuilder.directory(new File("C:\hello world\"));
This works like gem.
int result = 1;
final File batchFile = new File("C:\\hello world\\MyFile.bat");
final File outputFile = new File(String.format("C:\\hello world\\output_%tY%<tm%<td_%<tH%<tM%<tS.txt", System.currentTimeMillis()));
final ProcessBuilder processBuilder = new ProcessBuilder(batchFile.getAbsolutePath());
processBuilder.redirectErrorStream(true);
processBuilder.redirectOutput(outputFile);
processBuilder.directory(new File("C:\\hello world\\"));
try {
final Process process = processBuilder.start();
if (process.waitFor() == 0) {
result = 0;
}
System.out.println("Processed finished with status: " + result);
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
Did you try to escape quotes surrounding the path such as :
Runtime.getRuntime().exec(dosCommand + "\"" + destinationFilePath + batch + "\"")
I just solved this problem using a ProcessBuilder as well, however I gave the directory with a space to processBuilder.directory and ran the command with the bat file name.
ProcessBuilder pb = new ProcessBuilder("cmd", "/c", "start", "/wait", "export.bat");
pb.directory(new File(batDirectoryWithSpace));
pb.redirectError();
try {
Process process = pb.start();
System.out.println("Exited with " + process.waitFor());
}
catch (IOException | InterruptedException ex) {
Exceptions.printStackTrace(ex);
}

Open a cmd window and issue multiple commands

I have to open (or execute in the background) a cmd window out of my java application. It did this before and it worked totally fine:
public String getEnvVar(String envVarName) throws Exception {
String varName = "%" + envVarName + "%";
Process process = Runtime.getRuntime().exec(
new String[]{"cmd.exe", "/C", "echo " + varName}
);
BufferedReader input = new BufferedReader(
new InputStreamReader(process.getInputStream())
);
varName = input.readLine();
process.destroy();
...
My problem is: I have a different instance of a different class and tried to open a cmd window just the way it is done in the code above:
private void execute() {
try {
String batchData = batchContent();
Process process = Runtime.getRuntime().exec(new String[]{"cmd.exe", "/C", batchData});
new File(sourceFile).delete();
new File(sourceFolder).delete();
process.destroy();
} catch (IOException ie) {
}
}
But this doesn't work...I used google to figure out why, couldn't find a real reason for this.
Even
Process process = Runtime.getRuntime().exec(new String[]{"cmd.exe", "cd c:\\temp"});
does not change into the temp folder (which i created beforehand for testing reasons)
What's wrong?
EDIT//
I now tried:
private void upload() {
try {
//Process process = Runtime.getRuntime().exec(batchDataFile);
//Process process = Runtime.getRuntime().exec("cmd.exe /C " + batchDataFile);
Process process = Runtime.getRuntime().exec("cmd.exe /C " + "\"" + batchDataFile + "\"");
//new File(sourceCodeFile).delete();
//new File(batchDataFile).delete();
//new File(sourceCodeFolder).delete();
process.destroy();
} catch (IOException ie) {
ie.printStackTrace();
}
}
I additionally tried to run the generated batch skript without the Java app, it works as intended

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.

Categories