So, I wrote this code on java and it's taking some 6 second times to execute and give output. As I am not from coding background I was expecting if someone from this expert's group could help me optimize this little.
Below is my code also the PowerShell command runs within seconds. only this while loop is taking much time.
What I want to achieve is just get the list of drives which is HDD and print it.
Process p = Runtime.getRuntime().exec("powershell.exe Get-Partition -disknumber 1 | select DriveLetter");
BufferedReader in = new BufferedReader(new java.io.InputStreamReader(p.getInputStream()));
String line1 = "";
ArrayList<String> hddList = new ArrayList<String>();
while ((line1 = in.readLine()) != null) {
if (!line1.trim().isEmpty()) {
if (line1.contains("HDD")) {
hddList.add(line1.replaceAll(" +", "#").split("#")[0]+"#"+"HDD");
}
}
}
This seems to be an xy-problem, as you can easily get the drive letters in Java like
List<String> driveLetters = new ArrayList<>();
for(Path r: FileSystems.getDefault().getRootDirectories()) {
String s = r.toString();
if(s.length() == 3 && s.charAt(1) == ':') {
driveLetters.add(s.substring(0, 1));
}
}
since Java 7. This needs no interprocess communication and hence, has no such latency problems.
If you want to limit the result to fixed HDDs, you can use something like
List<String> driveLetters = new ArrayList<>();
for(Path r: FileSystems.getDefault().getRootDirectories()) {
String s = r.toString();
if(s.length() == 3 && s.charAt(1) == ':') try {
FileStore store = Files.getFileStore(r);
if(!Boolean.TRUE.equals(store.getAttribute("volume:isRemovable"))
&& !Boolean.TRUE.equals(store.getAttribute("volume:isCdrom"))) {
driveLetters.add(s.substring(0, 1));
}
}
catch(IOException ex) {} // no media in drive, obviously not an HDD then
}
As I said in my comments, I believe the issue is with the execution of the powerShell and not Java. See how quickly the following runs using the cmd.exe.
Here, all I'm doing is a directory listing and replacing <DIR> as though it was HDD.
Process p = Runtime.getRuntime().exec(
"cmd.exe /c dir".split("\\s+"));
System.out.println(p);
BufferedReader in = new BufferedReader(
new java.io.InputStreamReader(p.getInputStream()));
String line1 = "";
List<String> hddList = new ArrayList<String>();
while ((line1 = in.readLine()) != null) {
System.out.println(line1);
if (!line1.trim().isEmpty()) {
if (line1.contains("<DIR>")) {
hddList.add(line1.replaceAll(" +", "#").split("#")[0] + "#"
+ "HDD");
}
}
}
System.out.println(hddList);
You might be able to run cmd.exe as administrator and use related privileged commands to get the disk information. I have yet to determine how to do that without password input.
Related
I execute system command in android app, but I can't get right execute results.
Here is my code:
String cmd = "ls /";
try {
Process p = Runtime.getRuntime().exec(cmd);
InputStream stdout = p.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(stdout));
p.waitFor();
if (p.exitValue() != 0) {
System.out.println(p.exitValue());
Log.d("test",p.exitValue()+" ");
}
String s;
List<String> stdout_list = new ArrayList<>();
while ((s = reader.readLine()) != null) {
Log.d("test", s);
s = s + "\n";
stdout_list.add((String)s);
}
callableGetData.stdout_list = stdout_list;
} catch(Exception e) {
System.out.println(e);
}
cmd, such as ls, will get the wrong answer 1, but if I use ps -A, I will get right answers. The wrong answer 1, may be the exitValue().
What causes this?
See here for example. It says:
Exit status:
...
1 if minor problems (e.g., cannot access subdirectory)
Your app probably does not have sufficient privileges to ls the whole root directory /.
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;
}
}
I have a swing timer that runs every 30 seconds, it calls a method where I do a search for a few specific application's PIDs that I get from a list.
This is the code in the method that is called.
try {
Runtime r = Runtime.getRuntime();
Process p = r.exec("tasklist");
BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream()));
String inputLine = "";
while ((inputLine = in.readLine()) != null) {
System.out.println(inputLine);
for (int i = 0; i < runningAppList.size(); i++) {
if (inputLine.contains(runningAppList.get(i).getExecutableName())) {
appPIDNumber = inputLine.substring(28, 35).trim();
break;
} else {
appPIDNumber = "";
}
}
}
in.close();
} catch (IOException e) {
LoggingUtils.LogExceptions(LoggingConstants.ERROR, e.toString());
}
So if my app is running and I start the application I get the PID, but when I close the application it still shows the PID and does not clear it back to ""; I know I'm missing something small.
Thanks.
I think it is because of the runningAppList. If the application is closed, then that list might be empty, so the "while" loop will not be executed and the variable appPIDNumber will not be set to empty.
Second option is, that r.exec("tasklist") does not contain any line, after your application closed.
Anyway, seems you will have to set appPIDNumber to empty just before the "while" loop.
So here's the deal:
I have a node.js script that queries a mysql database of my own.
Simple select, nothing much.
If I run it from the command line I get my expected results without problem.(see below)
However, when I run said script from java using the code below for it to save the results in an array for later use, what happens is that those arrays will always be empty.
Even a straight prints show nothing.
public static ArrayList<String> scriptcaller(String command){
ArrayList<String> out = new ArrayList<String>();
ArrayList<String> errors = new ArrayList<String>();
BufferedReader bri, bre;
try {
String line;
Process p = Runtime.getRuntime().exec(command);
bri = new BufferedReader
(new InputStreamReader(p.getInputStream()));
bre = new BufferedReader
(new InputStreamReader(p.getErrorStream()));
//guardar linhas de outpur em out
while ((line = bri.readLine()) != null) {
System.out.println(line);
out.add(line);
}
bri.close();
//guardar linhas de errors em errors
while ((line = bre.readLine()) !=null) {
//System.out.println(line);
errors.add(line);
}
bre.close();
p.waitFor();
System.out.println("Done.");
}
catch (Exception err) {
err.printStackTrace();
}
return out;
}
The output of the script is something like this when executed straight in from the command line:
[{userID: mryuur,
type: 'energy',
value: '1337'}]
I have used the java function with other scripts and commands and it worked fine.
Here is part of the query script:
var userparam = "mryuur";
var querybody = 'SELECT * FROM GAP WHERE userID = "'+userparam+'"';
var query = connection.query(querybody, function(err, result) {
if (err) {
return console.log(err);
}
console.log(result);
//console.log("Done");
process.exit(0);
});
Thanks in advance.
EDIT
I tried to run the following script on a similar java function that takes several parameters.
(part of it)
var user, type, value, time;
// print process.argv
process.argv.forEach(function (val, index, array) {
console.log(index + ': ' + val);
if (index == 2)
{user = val}
if (index == 3)
{type = val}
if (index == 4)
{value = val}
if (index == 5)
{time = val}
});
connection.connect(function(err) {
// connected! (unless `err` is set)
});
var insertbody = 'INSERT INTO GAP(`userID`, `type`, `value`, `timestp`) VALUES ("'+user+'","'+type+'","'+value+'","'+time+'")'
var query = connection.query(insertbody, function(err, result) {
if (err) {
return console.log(err);
}
console.log(result);
//console.log("Done");
process.exit(0);
});
what happened was that the console.log where i print the parameters passed, for testing purposes, did show up in the java console but the console.log(result) to print the result of the insert did not. Note that both show accordingly when the script is executed straight from the command line.
I want to run a C/C++ program's exe file using java.......and handle its input and output......
my code is
import java.io.*;
class run2 {
public static void main(String[] args) throws java.io.IOException {
String[] command = new String[3];
command[0] = "cmd";
command[1] = "/C";
// command[2] = "java Run1";
command[2] = "start C:\\WE.EXE";
Process p = Runtime.getRuntime().exec(command);
String i = "20";
BufferedReader stdInput = new BufferedReader(new InputStreamReader(
p.getInputStream()));
BufferedWriter st = new BufferedWriter(new OutputStreamWriter(
p.getOutputStream()));
String s = null;
System.out.println("Here is the standard output of the command:\n");
s = stdInput.readLine();
System.out.println(s);
st.write(i);
st.newLine();
st.flush();
while ((s = stdInput.readLine()) != null) {
System.out.println("Stdout: " + s);
}
try {
System.out.println("Exit status = " + p.waitFor());
}
catch (InterruptedException e) {
}
stdInput.close();
}
}
i am getting an error which says pipes is closed
do help me out.....
Well, first of all, if there isn't a WE.EXE in C:/, that could be an issue. If no process is ever launched, of course you can't do anything with its input/output pipes.
However, presuming you have a WE.EXE, your error is probably at:
st.flush();
Your application is opening up WE.EXE in command prompt, or cmd.exe, who will take care of both standard input and standard output. Your call stdInput.readLine(); will wait until WE.EXE, and therefore cmd.exe, terminates, at which point the output stream will be closed (and you obviously can't write onto a closed pipe).
So if you want to handle input and output yourself, you should launch WE.exe directly, like:
Process p = Runtime.getRuntime().exec("C://WE.EXE");
Additionally, you may consider using ProcessBuilder instead of Runtime.exec.
Small detail, but consider using Java's naming conventions--for example, your class name would be Run2 (or something more descriptive) instead of run2.
You are trying to read from a stream (stdInput) that does not exist yet.
It won't exist until the WE.EXE program writes something to it.
Just wait until you send the commands to the program.
In other words, take out the first input line, and it will work fine.
//s = stdInput.readLine();
System.out.println(s);
st.write(i);
st.newLine();
st.flush();
while ((s = stdInput.readLine()) != null)
{ System.out.println("Stdout: " + s); }