Runtime.exec() returning null - java

I have seen similiar questions on this site, but none of them seem to address/solve my problem, so I figured there is something specifically wrong with my program. I am trying to execute a very simple command, which is to take a string of a process name from a textfield input and concatenate it to a command to return and print the title of the window. This is my code:
String line;
Process p = null;
try
{
String command = "tasklist /v /fo list /fi \"imagename eq " + tf.getText().trim() + "*\"| find /i \"window title:\"\n";
p = Runtime.getRuntime().exec(command);
BufferedReader input =
new BufferedReader(new InputStreamReader(p.getInputStream()));
System.out.println(command);
while ((line = input.readLine()) != null)
{
line = line.trim();
System.out.println(line);
}
System.out.println("done");
}
catch (IOException ioException)
{
ioException.printStackTrace();
}
However, the line returned by the InputStream is always null, even though if I put the command used in .exec() into cmd (I printed it so I know they are the exact same), it works properly, albeit after a 5 seconds or so of delay. I tried it with 2 different process names and they both worked on cmd, but not in this java program. This is the output of the above code, in case that helps (the blank line is presumably from the \n at the end of the command string):
tasklist /v /fo list /fi "imagename eq notepad*"| find /i "window title:"
done
I tried adding p.waitFor() after calling .exec(), but that didn't seem to change anything. So what am I doing wrong here?

You have two problems with launching the command. Firstly you are ignoring error stream so don't see the actual problem.
Replace p = Runtime.getRuntime().exec(command); with ProcessBuilder to get access to error message:
ProcessBuilder pb = new ProcessBuilder(command);
pb.redirectErrorStream();
p = pb.start();
This will tell you that tasklist is not a process. Normally using full pathname would fix this type of error, but as you are using pipe the whole command must sent to to CMD.EXE to interpret pipe components correctly. Run CMD.EXE then your piped command:
ProcessBuilder pb = new ProcessBuilder("cmd.exe", "/c", command);
pb.redirectErrorStream();
p = pb.start();
Prints:
tasklist /v /fo list /fi "imagename eq notepad*"| find /i "window title:"
Window Title: Notepad++
done
It's also easier to read STDOUT with simple transfer:
try(var stdout = p.getInputStream()) {
stdout.transferTo(System.out); // or where-ever
}

Related

Run cmd as administrator using java under Windows

Using java, I run cmd to be able to execute a ttl file.
My code:
try {
String[] command = new String[] {"cmd.exe", "/c", "cd C:\software\teraterm", "& TTPMacro C:\file\execute.ttl param1 param2 param3"};
Process p = Runtime.getRuntime().exec(command);
p.waitFor();
} catch (Exception e) {
throw e;
}
But I want cmd to be run as admin
so I added runas /savecred /user:.\Administrator in my code,
but it is not working anymore:
try {
String[] command = new String[] {"cmd.exe", "/c", "runas /savecred /user:.\\Administrator", "cd C:\software\teraterm", "& TTPMacro C:\file\execute.ttl param1 param2 param3"};
Process p = Runtime.getRuntime().exec(command);
p.waitFor();
} catch (Exception e) {
throw e;
}
What is wrong with this?
I've updated code to check input stream, but there is no output
try {
String[] command = new String[] {"cmd.exe", "/c", "runas /savecred /user:.\\Administrator", "cd C:\software\teraterm", "& TTPMacro C:\file\execute.ttl param1 param2 param3"};
Process p = Runtime.getRuntime().exec(command);
BufferedReader br=new BufferedReader(new InputStreamReader(p.getInputStream()));
String l;
while((l=br.readLine()) != null){
System.out.print(l);
}
p.waitFor();
} catch (Exception e) {
throw e;
}
Meta: although not stated, this Q and A is only for Windows and is useless on other systems
runas can only run a program (with arguments); cd is a builtin function of cmd not a program. Also cmdone & cmdtwo is a feature of cmd, not something runas can do. You need to put your commands into a cmd /c invocation, much as you did for running directly from Java Runtime.exec (which also can only run a single program), except that runas requires its program-to-run to be exactly one argument, not optionally several that are (re)joined. So:
String[] command = new String[]{"runas","/user:administrator","/savecred", // these must be separated args
"cmd /c cd directory & executable data"}; // these must be all one argument
Also in Java String literals, backslash is used as an escape character, so you must double each one (in pathnames or otherwise).
Finally if runas doesn't have already-saved credentials it prompts for the password. This prompt is not a line, so you can't read it with BufferedReader.readLine(). You can read it as bytes (into an array) with the input stream, or chars (ditto) with the InputStreamReader. However, as something of a hack, since runas doesn't pass its own stdhandles to its child but instead a new console window, you can just ignore the prompt and always write the password to p.getOutputStream() whether it's needed or not, and if it's not it will be discarded.

Run exec file using Java on Mac

I need to start a server using bash, so I had created an UNIX shell , but I am not able to execute it with Java from Eclipse.
I tried the following code which doesn't work :
Process proc = Runtime.getRuntime().exec(./startServer);
Here is content of the startServer file :
#!/bin/bash
cd /Users/sujitsoni/Documents/bet/client
npm start
You can try the following two options.
Option 1
Process proc = Runtime.getRuntime().exec("/bin/bash", "-c", "<Abosulte Path>/startServer");
Option 2
ProcessBuilder pb = new ProcessBuilder("/bin/bash", "-c", "<Absolute Path>/startServer");
pb.directory(new File("<Absolute Path>"));
Process proc = pb.start();
A couple Of things can go wrong:
The path to the file you have given might be wrong for eclipse it can take relative path but from the command line, it will take the absolute path.
error=13, Permission denied - If the script file doesn't have required permissions. In your scenario, that might not the case as you are not getting any error.
At last, you are executing the script by java program so the output of your script will not be printed out. In your scenario, this might be the case. You need to capture the output of script from BufferedReade and print it. ( In your case server might have started but you are not seeing the logs/output of the script.
See the code sample below for printing output.
public static void main(String[] args) throws IOException, InterruptedException {
Process proc = Runtime.getRuntime().exec("./startServer");
proc.waitFor();
StringBuffer output = new StringBuffer();
BufferedReader reader = new BufferedReader(new InputStreamReader(proc.getInputStream()));
String line = "";
while ((line = reader.readLine()) != null) {
output.append(line + "\n");
}
System.out.println(output);
}

How to run exec from Java for netsh?

The following works fine when i type it in directly into cmd.exe:
netsh wlan connect name="Profile Name" ssid=XXXXXX
However when i try to do this from java it does not work, neither does it throw any exception. It is silently ignored:
Runtime.getRuntime().exec("cmd netsh wlan connect name=\"Profile Name\" ssid=XXXXX ") ; `
How can i improve the code ?
First try removing the cmd parameter (you don't need to run this interpreter, just netsh).
Else it may be due to whitespace characters in this command line (be careful of whitespace in SSID for example). You may want to try Runtime.exec(String[] cmdarray) or java.lang.ProcessBuilder instead to specify each parameter individually.
Examples:
Runtime.getRuntime().exec(new String[] {"netsh", "wlan", "connect", "name=\"Profile Name\"", "ssid=XXXXX"});
or (complete example):
ProcessBuilder pb = new ProcessBuilder("netsh", "wlan", "connect",
"name=\"Profile Name\"", "ssid=XXXXX");
pb.redirectErrorStream(true);
Process process = pb.start();
BufferedReader reader = new BufferedReader(
new InputStreamReader(process.getInputStream()));
String line = null;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}

fetch nth line of a text file using non-interactive shell script

i need to fetch the nth line of a txt file using shell script.
my text file is like
abc
xyz
i need to fetch the 2nd line and store it in a variable
i've tried all combinations using commands like :
sed
awk
head
tail
cat
... etc
problem is, when the script is called from the terminal, all these commands work fine.
but when i call the same shell script, from my java file, these commands do not work.
I expect, it has something to do with the non-interactive shell.
Please help
PS : using read command i'm able to store the first line in a variable.
read -r i<edit.txt
here , "i" is the variable and edit.txt is my txt file.
but i cant figure out, how to get the second line.
thanks in advance
edit :
ALso the script exits, when i use these "non-working" commands, And none of the remaining commands is executed.
already tried commands :
i=`awk 'N==2' edit.txt`
i=$(tail -n 1 edit.txt)
i=$(cat edit.txt | awk 'N==2')
i=$(grep "x" edit.txt)
java code:
try
{
ProcessBuilder pb = new ProcessBuilder("./myScript.sh",someParam);
pb.environment().put("PATH", "OtherPath");
Process p = pb.start();
InputStreamReader isr = new InputStreamReader(p.getInputStream());
BufferedReader br = new BufferedReader(isr);
String line ;
while((line = br.readLine()) != null)
System.out.println(line);
int exitVal = p.waitFor();
}catch(Exception e)
{ e.printStackTrace(); }
}
myscript.sh
read -r i<edit.txt
echo "session is : "$i #this prints abc, as required.
resFile=$(echo `sed -n '2p' edit.txt`) #this ans other similar commands donot do anything.
echo "file path is : "$resFile
An efficient way to print nth line from a file (especially suited for large files):
sed '2q;d' file
This sed command quits just after printing 2nd line rather than reading file till the end.
To store this in a variable:
line=$(sed '2q;d' file)
OR using a variable for line #:
n=2
line=$(sed $n'q;d' file)
UPDATE:
Java Code:
try {
ProcessBuilder pb = new ProcessBuilder("/bin/bash", "/full/path/of/myScript.sh" );
Process pr = pb.start();
InputStreamReader isr = new InputStreamReader(pr.getInputStream());
BufferedReader br = new BufferedReader(isr);
String line;
while((line = br.readLine()) != null)
System.out.println(line);
int exitVal = pr.waitFor();
System.out.println("exitVal: " + exitVal);
} catch(Exception e) { e.printStackTrace(); }
Shell script:
f=$(dirname $0)/edit.txt
read -r i < "$f"
echo "session is: $i"
echo -n "file path is: "
sed '2q;d' "$f"
Try this:
tail -n+X file.txt | head -1
where X is your line number:
tail -n+4 file.txt | head -1
for the 4th line.

Run CMD equivalent in OSX?

I'm using this code to make my Java program open a (visible) CMD window:
try {
String line;
Process p = Runtime.getRuntime().exec("cmd /C start \"Render\" \"" + myPath + "\\punchRender.cmd\"");
BufferedReader input =
new BufferedReader(new InputStreamReader(p.getInputStream()));
while ((line = input.readLine()) != null) {
System.out.println(line);
jLabel7.setText(line);
}
input.close();
} catch (Exception err) {
err.printStackTrace();
}
and I've been trying to do the same thing with the OSX terminal, this is where I'm at right now:
try {
String line;
Process p = Runtime.getRuntime().exec("sh " + myPath + "/punchRender.sh");
BufferedReader input =
new BufferedReader(new InputStreamReader(p.getInputStream()));
while ((line = input.readLine()) != null) {
System.out.println(line);
jLabel7.setText(line);
}
input.close();
} catch (Exception err) {
err.printStackTrace();
}
So far, no luck :( Any suggestions? The .sh file isn't even running...
I would just make sure your shell script has the execute bits on and just pass in the shell script file name.
Process p = Runtime.getRuntime().exec(myPath + "/punchRender.sh")
Edit:
I don't know Java specifically if there is anyway to set file permissions for Unix/Linux with it to set the eXecute bit or how to escape quotes. But It would be something like this:
Process chmod = Runtime.getRuntime().exec("chmod u+x \"" + myPath + "/punchRenderer.sh\"")
This should work. Not only running the script, but opening a terminal also:
Process p = Runtime.getRuntime().exec("open -a /Applications/Utilities/Terminal.app \"" + myPath + " /punchRender.sh\"");
If you want a new visible Terminal window, you can't run the shell directly. You need to start Terminal and then run a .command file, not a shell script. I'm not sure how hard it would be to connect the stdout of that command to your Java process. You might have to figure out some other way of getting the output into the terminal.
By the way, I tried your code in a class on my own Mac at home, and it ran a .sh file just fine. I was running the java class from the command line. Maybe sh just isn't in your PATH.
I assume you've checked that the .sh file is executable, haven't you?
Can I suggest you capture the standard error as well as the standard output, and dump that. That should give you some idea as to what's going on (it's good practise generally).
You may need to gather standard output and standard error in different threads to avoid blocking issues. See here for a StreamGobbler

Categories

Resources