Get the Infornation from getRuntime().exec hat java app hangs up - java

My code so far:
public static void getTasklist(Table table, Login login){
for(TableItem tableItem : table.getItems()){
try {
if(tableItem.getChecked()){
String command = ("cmd.exe /k tasklist /s " + tableItem.getText(3) + " /U .\\" + SettingsManager.getSetting(login, "Current-User") + " /p " + SettingsManager.getSetting(login, SettingsManager.getSetting(login, "Current-User")+"-PW"));
Process p = Runtime.getRuntime().exec(command);
BufferedReader in = new BufferedReader(
new InputStreamReader(p.getInputStream()));
String line = null;
while ((line = in.readLine()) != null) {
System.out.println(line);
}
}
}
catch (IOException e) {
}
}
}
What I want to do: get task list information from a computer and print it to console (later print it to a window maybe). The host name from the computer comes from the checked table (tableItem.getText(3)) and the credentials comes from something I called settingsmanager (SettingsManager.getSetting....).
What works ATM: I get the Information and it got printed to console but after the last line the app hangs up.. I assume that the while loop never breaks but I am not sure about that..

Related

Exception occurred while executing 'put'

I'm trying to run an adb shell command programmatically through an app to change the rtt_calling_mode variable value, but I'm running into this error.
Exception occurred while executing 'put':
java.lang.NullPointerException
at java.util.Objects.requireNonNull(Objects.java:220)
at com.android.server.appop.AppOpsService.checkPackage(AppOpsService.java:2969)
at android.app.AppOpsManager.checkPackage(AppOpsManager.java:7697)
at android.content.ContentProvider.getCallingPackage(ContentProvider.java:954)
at com.android.providers.settings.SettingsProvider.mutateSecureSetting(SettingsProvider.java:1732)
at com.android.providers.settings.SettingsProvider.insertSecureSetting(SettingsProvider.java:1652)
at com.android.providers.settings.SettingsProvider.call(SettingsProvider.java:412)
at android.content.ContentProvider.call(ContentProvider.java:2448)
at android.content.ContentProvider$Transport.call(ContentProvider.java:517)
at com.android.providers.settings.SettingsService$MyShellCommand.putForUser(SettingsService.java:375)
at com.android.providers.settings.SettingsService$MyShellCommand.onCommand(SettingsService.java:277)
at android.os.BasicShellCommandHandler.exec(BasicShellCommandHandler.java:98)
at android.os.ShellCommand.exec(ShellCommand.java:44)
at com.android.providers.settings.SettingsService.onShellCommand(SettingsService.java:49)
at android.os.Binder.shellCommand(Binder.java:929)
at android.os.Binder.onTransact(Binder.java:813)
at android.os.Binder.execTransactInternal(Binder.java:1159)
at android.os.Binder.execTransact(Binder.java:1123)
When running on A10 I was able to run this command perfectly fine and It would change the RTT variable as if I ran the command 'adb shell settings put secure rtt_calling_mode0 1' via the command prompt. But now on an A11 build I receive this error. I'm not sure what could be causing this issue and why it now has an issue with 'put' now. Also not sure where the NullPointerException is coming from either. Does anyone know what could be causing this issue? Below is the code that's throwing the error when its run.
public static String setRealTimeText(int simSlot, int enabled){
String command = "settings put secure rtt_calling_mode" + slot + " " + enabled;
try {
Process process = Runtime.getRuntime().exec(command);
BufferedReader output = new BufferedReader(new InputStreamReader(process.getInputStream()));
BufferedReader errorOutput = new BufferedReader(new InputStreamReader(process.getErrorStream()));
//get the error output
String s = "";
String outputString = "";
if (errorOutput.readLine() != null) {
while ((s = errorOutput.readLine()) != null) {
outputString += " " + s + "\n";
}
return outputString;
}
//get the console output
while ((s = output.readLine()) != null) {
outputString += "- " + s + "\n";
}
return "RTT was enabled"
} catch (Exception e) {
e.printStackTrace();
return e.toString();
}
}
If you do not need to issue a shell command, you can programmatically do
Settings.Secure.putInt(getContentResolver(), Settings.Secure.RTT_CALLING_MODE, 1);
But you need root access to do this. Only system apps have permission to change secure settings. This might as well be the cause for the exception when running the shell command.

Running command from Java code doesn't work, but same string works manually through cmd.exe

I'm launching from my jar 3 programs with their own parameters.
First and second programs do their job, but not the second one.
Here the code
Runtime rt = Runtime.getRuntime();
String cmdGet= "something";
try {
infolog("Executing command: " + cmdGet);
rt.exec(cmdGet);
}
catch(Exception ex){
infolog("Unable to launch program 2");
saveLog();
}
Here the command for something
D:\Root\Module\Translators\L2Fo\SE_Draft_Update.exe -se_file="F:\Disp\Stage\DC\Ude34ea24x591ecb1c412x\M8486.dft" -input_file="F:\Disp\Stage\DC\Ude34ea24x591ecb1c412x\result\AttributeFile_M8486.txt" -log_file="F:\Disp\Stage\DC\Ude34ea24x591ecb1c412x\result\SELogg_M8486.txt"
In the log I find the proper command launched, but I see that its jobs are not done. So by copying the string manually in the cmd prompt it works
The third program after this one works too.
I do not understand why.
Sometimes a command needs its own cmd-shell.
Then you had to add a "CMD.EXE /C " prefix. This is the reason why
the 'something' line works fine in the cmd-Window.
if (b_shell == true) cmd = "CMD.EXE /C " + cmdstr;
else cmd = cmdstr;
...
rt.exec(cmd);
I pass the b_shell as argument to a wrapper method:
public static void systemCall(String cmdstr,boolean b_shell,Path logfile) throws IOException
Sorry for that answer, perhaps you like to try a version which
is able to wait for the terminating command and returns the output of the command as an ArrayList.
/**
* Executes command 'cmdstr'. The output of the command is stored in a ArrayList-String array
* #param cmdstr The command line to be executed not containing a redirect to an outputfile ( > x.txt )
* #param b_wait If true the command waits until it is finished and 'errmsg' contains the exit value
* #param b_shell If true the command will be started in a shell (uses prefix CMD.EXE /C)
* #param errmsg OUT: Error message
* #return ArrayList-String output or null on error, see errmsg
* #since Last change: 2014.04.30
*/
public static ArrayList<String> systemCallOutputArray(String cmdstr,boolean b_wait,boolean b_shell,/*IO*/StringBuffer errmsg)
{
final String fn="systemCallOutputArray()";
errmsg.setLength(0);
if (cmdstr == null || cmdstr.isEmpty()) { errmsg.append(fn + ": Invalid arg. 'cmdstr' (null or empty)"); return null; }
ArrayList<String> output = new ArrayList<String>();
String cmd ="";
try
{
int exit_value = -1;
Runtime r = Runtime.getRuntime();
Process p = r.exec(cmd);
String line="";
if (b_wait == true)
{
p.waitFor(); // waits until prozess is terminated, throws InterruptedException if wait is interrupted
exit_value = p.exitValue();
BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));
while ((line = input.readLine()) != null)
{ if (line.isEmpty() == false) output.add(line);
}
input.close();
return output;
}
// the following lines are for b_wait = false
BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));
while ((line = input.readLine()) != null)
{ if (line.isEmpty() == false) output.add(line);
}
input.close();
return output;
}
catch (Exception e)
{
errmsg.append(fn + " failed: " + e.toString() + " cmd: '" + cmd + "'");
return null;
}
} //---------------- end of systemCallOutputArray()

Executing grep command on Linux from Java always returning null

I am executing grep command from java on a linux file. Its always returning null for the following code.
Process p;
String matchStr="testmatch";
String output = null;
try {
String command = "grep \""+matchStr+"\" "+ filename;
System.out.println("Running command: " + command);
p = Runtime.getRuntime().exec(command);
System.out.println("***********************************");
System.out.println("***********************************");
System.out.println("***********************************");
p.waitFor();
BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
while (br.readLine() != null) {
System.out.println("in while loop");
System.out.println("in while loop");
System.out.println("in while loop");
System.out.println(output);
System.out.println("***********************************");
System.out.println("***********************************");
System.out.println("***********************************");
System.out.println("***********************************");
// Process your output here
}
System.out.println("exit: " + p.exitValue());
p.destroy();
} catch (Exception e) {
e.printStackTrace();
}
If i grep it directly it shows output but from java it never gets into while loop.
Please suggest whats wrong here.
The problem is that you do not write anything to output so it stays null. I guess you have to rewrite your while loop like this
while ((output = br.readLine()) != null) {
// Process your output here
}
Take a note that this syntax is discouraged by most style check due to it's abmiguity
Also it's a good idea to place p.waitFor() after while loop so grep would not hang on flushig std(err|out).
UPDATE
Also it is a good idea to use ProcessBuilder (available since java-7) instead of Runtime.getRuntime().exec(...) because you will have more control over the process i.e
final ProcessBuilder builder = new ProcessBuilder();
builder.command("grep", matchStr, filename);
// redirect stderr to stdout
builder.redirectErrorStream(true);
final Process process = builder.start();
BufferedReader br = new BufferedReader(
new InputStreamReader(process.getInputStream()));
String output = null;
while ((output = br.readLine()) != null) {
System.out.println(output);
// Process your output here
}
process.waitFor();
After turning your code into a https://stackoverflow.com/help/mcve it works for me.
Here the file does not exist:
robert#habanero:~$ rm /home/robert/greptest.txt
robert#habanero:~$ javac GrepTest.java && java GrepTest
Running command: grep test /home/robert/greptest.txt
exit: 2
Now the file does exist but does not contain the text to be found:
robert#habanero:~$ echo not found > /home/robert/greptest.txt
robert#habanero:~$ javac GrepTest.java && java GrepTest
Running command: grep test /home/robert/greptest.txt
exit: 1
Now the file exists and contains the text:
robert#habanero:~$ echo test this > /home/robert/greptest.txt
robert#habanero:~$ javac GrepTest.java && java GrepTest
Running command: grep test /home/robert/greptest.txt
test this
exit: 0
Here is the code:
import java.io.*;
public class GrepTest {
public static void main(String[] args) throws Exception {
String command = "grep test /home/robert/greptest.txt";
System.out.println("Running command: " + command);
Process p = Runtime.getRuntime().exec(command);
p.waitFor();
BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
String output;
while ((output = br.readLine()) != null) {
System.out.println(output);
}
System.out.println("exit: " + p.exitValue());
p.destroy();
}
}
I was recently struggling with a similar issue, and I believe I the solution I found is an answer also to your problem (though your question is a bit malformed as others have pointed out).
The issue pertrains to the quote marks around your search string,
\""+matchStr+"\"
The java exec command will literally deliver these to the grep command, and instead of searching for matchStr, grep will be looking for "matchStr", and the results will not be what you are expecting.
This applies also in case one is executing the command as an array like
final Process process = Runtime.getRuntime().exec(new String[] { "grep", "-C1000", searchString, fileName } );
Pass the plain searchString without including quotation marks into the string.

Passing windows credentials programmatically

I have a VB script to which I need to pass username and password.
I want to run this VB script through Java code programmatically.
Is there a way that I can pass the Windows credentials to the VB script in Java programmatically?
You can have the credentials on the OS environment and read them from there:
String credentials = System.getenv().get("encrypted_credentials_or_something");
And then run your command from Java. However, Runtime.exec() won't work in some cases:
When the command is not on the System's PATH
When arguments are involved
When you want to have access to the process output
When you need to be able to kill the process
When you need to check if it terminated successfully or in error (status code != 0 - which is why you write System.exit(int) to terminate a Java application. The System.exit(1), for example, indicates abnormal termination)
That's why I created this utility class to execute external processes with arguments and everything. It works very well for me:
import java.io.*;
import java.util.*;
public class ExternalCommandHelper {
public static final void executeProcess(File directory, String command) throws Exception {
InputStreamReader in = null;
try {
//creates a ProcessBuilder with the command and its arguments
ProcessBuilder builder = new ProcessBuilder(extractCommandWithArguments(command));
//errors will be printed to the standard output
builder.redirectErrorStream(true);
//directory from where the command will be executed
builder.directory(directory);
//starts the process
Process pid = builder.start();
//gets the process output so you can print it if you want
in = new InputStreamReader(pid.getInputStream());
//simply prints the output while the process is being executed
BufferedReader reader = new BufferedReader(in);
String line = null;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
int status = 0;
//waits for the process to finish. Expects status 0 no error. Throws exception if the status code is anything but 0.
if ((status = pid.waitFor()) != 0) {
throw new IllegalStateException("Error executing " + command + " in " + directory.getAbsolutePath() + ". Error code: " + status);
}
} finally {
if (in != null) {
in.close();
}
}
}
//Splits the command and arguments. A bit more reliable than using String.split()
private static String[] extractCommandWithArguments(String command) {
StringTokenizer st = new StringTokenizer(command);
String[] cmdWithArgs = new String[st.countTokens()];
for (int i = 0; st.hasMoreTokens(); i++) {
cmdWithArgs[i] = st.nextToken();
}
return cmdWithArgs;
}
}

how to get error message when excuting java command?

I call a class which is located somewhere in a jar file (using java -classpath path/file.jar classname) within my java code.
This work well but only if the command is well formed. If I make a mistake the getRuntime().exect(command) just doesn't say anything. Bellow I have the working command invocation. I would like to get the error message when the command doesn't work. If I make a mistake in a cmd (windows) I get a proper error and I can fix it. But not within my java application.
I left a 'if(input.ready())' since if I don't the program freezes when the command line is incorrect. This happens when executing 'input.readLine()'.
// Execute a command with an argument that contains a space
String[] genKOSCommand = new String[] {
"java",
"-classpath",
Config.XDSI_TEST_KIT_HOME + "/xdsitest/lib/xdsitest.jar;"
+ Config.XDSI_TEST_KIT_HOME + "/xdsitest/classes",
"ca.etsmtl.ihe.xdsitest.docsource.SimplePublisher", "-k",
"C:/Softmedical/Viewer_Test/xdsi-testkit-2.0.4/xdsihome/usr/data/image14.dcm" };
Process child = Runtime.getRuntime().exec(genKOSCommand);
BufferedReader input = new BufferedReader(new InputStreamReader(
child.getInputStream()), 13107200);
String line = null;
if (input.ready()) {
while ((line = input.readLine()) != null) {
System.out.println(line);
}
try {
child.waitFor();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Have any advice on how to get an error from the executed command?
Thank you
By using getErrorStream:
BufferedReader errinput = new BufferedReader(new InputStreamReader(
child.getErrorStream()));
When processing the input from the different streams, it is better to do it in a different thread (since those calls (readLine etc.) are blocking calls.
Here's a bit more complete piece of code to print out errors received upon running some command via Process/Runtime:
final String command = "/bin/bash -c cat foo.txt | some.app";
Process p;
try {
p = Runtime.getRuntime().exec(command);
} catch (final IOException e) {
e.printStackTrace();
}
//Wait to get exit value
try {
p.waitFor();
final int exitValue = p.waitFor();
if (exitValue == 0)
System.out.println("Successfully executed the command: " + command);
else {
System.out.println("Failed to execute the following command: " + command + " due to the following error(s):");
try (final BufferedReader b = new BufferedReader(new InputStreamReader(p.getErrorStream()))) {
String line;
if ((line = b.readLine()) != null)
System.out.println(line);
} catch (final IOException e) {
e.printStackTrace();
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
Isn't Process.getErrorStream what you want?

Categories