Java library for finding executables - java

I am using the the ProcessBuilder class to execute executables on Windows and Linux.
Is there an easy way to find these executables without knowing the directory path to the executable.
e.g.
//which command functionality
String executable = which("executable_name");
List<String> command = new ArrayList<String>();
command.add(executable);
ProcessBuilder builder = new ProcessBuilder(command);
..
..
It would be great if there was a function like the which command on linux?
Any ideas or will I have to loop over and parse the PATH environment variables using the
System.getenv("PATH");

Use the where command on Windows.
WHERE [/R dir] [/Q] [/F] [/T] pattern
If you do not specify a search directory using /R, it searches the current directory and in the paths specified by the PATH environment variable. Here's a sample code that finds the two locations where notepad.exe resides on Windows.
String searchCmd;
if (System.getProperty("os.name").contains("Windows")) {
searchCmd = "where";
} else { // I'm assuming Linux here
searchCmd = "which";
}
ProcessBuilder procBuilder = new ProcessBuilder(searchCmd, "notepad.exe");
Process process = procBuilder.start();
ArrayList<String> filePaths = new ArrayList<String>();
Scanner scanner = new Scanner(process.getInputStream());
while (scanner.hasNextLine()) {
filePaths.add(scanner.nextLine());
}
scanner.close();
System.out.println(filePaths);
Output:
[C:\Windows\System32\notepad.exe, C:\Windows\notepad.exe]
Note: I've only tested this on Windows. You may have to modify (probably the command options and the way you parse which output) to make it work on Linux.

Related

ProcessBuilder can't find custom .exe

I am currently trying to write a small program in java which should take over the job of an old batch script I've been using.
This batch script executes a program called sum.exe (Supermicro Update Manager).
However, no matter which way I try, the program either does not respond, or straight up tells me it can't find the file in the directory where the file is.
boolean isWindows = System.getProperty("os.name").toLowerCase().startsWith("windows");
ProcessBuilder builder = new ProcessBuilder("C:\\Users\\[Username]\\SUM\\sum.exe");
if (isWindows) {
builder.command("sum.exe", "-i 192.168.4.10 -u ADMIN -p ADMIN -c CheckOOBSupport");
} else {
builder.command("sh", "-c", "ls");
}
builder.redirectErrorStream(true);
Process process = builder.start();
StreamGobbler streamGobbler = new StreamGobbler(process.getInputStream(), System.out::println);
StreamGobbler streamGobblerErrors = new StreamGobbler(process.getErrorStream(), System.out::println);
Executors.newSingleThreadExecutor().submit(streamGobbler);
Executors.newSingleThreadExecutor().submit(streamGobblerErrors);
int exitCode = process.waitFor();
assert exitCode == 0;
This is the code I currently have. The command I'm trying to call here will 100% give an error, so I made sure to redirect those as well.
As far as I understood, there are 3 different ways to set a Filepath for the Processbuilder.
Either you:
Set the path in the constructor
Set the path between your executable and arguments in the .command() method
Or you set the directory of the builder by creating a new file (and using System.Property)
I have a complete copy of the SUM-Folder under: C:\Users\[Username]\SUM, and I have tried all 3 options listed above with this, but always got the error message that the system could not find the file specified
Additionally, I'm still not sure if the command would even work this way. I have only ever used sum.exe via batch-Script or cmd.exe itself, so wouldn't the command need to be
builder.command("cmd.exe", "sum.exe -i 192.168.4.10 -u ADMIN -p ADMIN -c CheckOOBSupport)
instead?
Can anyone tell me what I'm doing wrong?
Thanks!
The ProcessBuilder command line is passed in the constructor or the command() method so in your example you've overridden the value used.
Choose the way you need:
ProcessBuilder builder = new ProcessBuilder("C:\\Users\\[Username]\\SUM\\sum.exe",
"-i", "192.168.4.10",
"-u", "ADMIN","-p", "ADMIN",
"-c", "CheckOOBSupport");
or
ProcessBuilder builder = new ProcessBuilder();
builder.command("sum.exe",
"-i", "192.168.4.10",
"-u", "ADMIN","-p", "ADMIN",
"-c", "CheckOOBSupport");
Note also that the arguments for the command need to supplied as separate string values rather than all concatenated together as one value, and you need absolute path to "sum.exe" if that is not found in the current directory or under a directory of environment variable "Path".

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 });

How can I create an independent Process with ProcessBuilder or set the working directory with exec()

I want to call a Process which is independent from the original Process. So I could use Runtime.Runtime.getRuntime().exec("java -Xms256M -Xmx256M -jar /home/HauptServer/Games/game1/cloud.jar -p "+port) but this will not set the working directory. So I used ProcessBuilder an tried this: ProcessBuilder prb = new ProcessBuilder("java","-Xms256M","-Xmx256M","-jar","cloud.jar","-p",""+port).directory(new File("/home/HauptServer/Games/game1")); but in this case it is not running independent from my original Process.
Dou you have any solutions?
Use Runtime.getRuntime().exec(String[] cmdarray, String[] envp, File dir)
From the documentation
Executes the specified command and arguments in a separate process
with the specified environment and working directory.
Do not use a single line command (java -jar ...) . Use the cmdarray[] and specify at dir the working directory
Example
String cmdArray[] = new String[7];
cmdArray[0] = "java";
cmdArray[1] = "-Xms256M";
cmdArray[2] = "-Xmx256M";
cmdArray[3] = "-jar";
cmdArray[4] = "/home/HauptServer/Games/game1/cloud.jar";
cmdArray[5] = "-p";
cmdArray[6] = port;

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();

Categories

Resources