Java - Run Powershell and parse commands to it - java

iam working on a project for a Service Desk. This Service Desk have round about 10 various tools to get the result for the customers. I already have put this tools to one Java-Tool together.
One thing do not want work.
The customers work on several XenApp/XenDesktop Servers. From the Server the customers ar loged in, i wanna get the RAM Avarage Util to show them in the GUI of my tool.
I wanne run a powershell ones and paste multiple times commands to the powershell. But it want work. In my example the program hangs in the while loop
while(!file.exists() & !file.canWrite()){}
after it runs one time.
My question is, can i run a powershell once and paste commands to it multiple times? In C# ive tryed it and it works. But i want rewrite 7000 lines of code in C#.
Sorry for my bad english. I hope you understand my problem and can help me.
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
import javax.security.auth.login.LoginException;
public class SystemAvarageUtil {
public static void getSystemAvarageUtil(String desktopServer, String appServer, String personalNummer) throws IOException, InterruptedException{
final Process process = Runtime.getRuntime().exec("PowerShell -NoExit -Command -");
while(personalNummer.equals("XXXXXX")){
File file = new File("H:\\sdassistence\\tmp\\Util.tmp");
if(file.exists()){
file.delete();
}
PrintWriter commands = new PrintWriter(process.getOutputStream(),true);
//desktopServer RAM
commands.println("$ComputerNameDesktop=\""+ desktopServer +"\"");
commands.println("$ComputerSystemDesktop = Get-WmiObject -ComputerName $ComputerNameDesktop -Class Win32_operatingsystem -Property CSName, TotalVisibleMemorySize, FreePhysicalMemory");
commands.println("$MachineNameDesktop = $ComputerSystemDesktop.CSName");
commands.println("$FreePhysicalMemoryDesktop = ($ComputerSystemDesktop.FreePhysicalMemory) / (1mb)");
commands.println("$TotalVisibleMemorySizeDesktop = ($ComputerSystemDesktop.TotalVisibleMemorySize) / (1mb)");
commands.println("$TotalVisibleMemorySizeRDesktop = \"{0:N2}\" -f $TotalVisibleMemorySizeDesktop");
commands.println("$TotalFreeMemPercDesktop = ($FreePhysicalMemoryDesktop/$TotalVisibleMemorySizeDesktop)*100");
commands.println("$TotalFreeMemPercRDesktop = \"{0:N2}\" -f $TotalFreeMemPercDesktop");
//commands.println("$TotalVisibleMemorySizeRDesktop GB");
//commands.println("$TotalFreeMemPercRDesktop %");
//appServer RAM
commands.println("$ComputerNameApp=\""+ appServer +"\"");
commands.println("$ComputerSystemApp = Get-WmiObject -ComputerName $ComputerNameApp -Class Win32_operatingsystem -Property CSName, TotalVisibleMemorySize, FreePhysicalMemory");
commands.println("$MachineNameApp = $ComputerSystemApp.CSName");
commands.println("$FreePhysicalMemoryApp = ($ComputerSystemApp.FreePhysicalMemory) / (1mb)");
commands.println("$TotalVisibleMemorySizeApp = ($ComputerSystemApp.TotalVisibleMemorySize) / (1mb)");
commands.println("$TotalVisibleMemorySizeRApp = \"{0:N2}\" -f $TotalVisibleMemorySizeApp");
commands.println("$TotalFreeMemPercApp = ($FreePhysicalMemoryApp/$TotalVisibleMemorySizeApp)*100");
commands.println("$TotalFreeMemPercRApp = \"{0:N2}\" -f $TotalFreeMemPercApp");
//commands.println("$TotalVisibleMemorySizeRApp GB");
//commands.println("$TotalFreeMemPercRApp %");
commands.println("$TotalVisibleMemorySizeRDesktop+\";\"+$TotalFreeMemPercRDesktop+\";\"+$TotalVisibleMemorySizeRApp+\";\"+$TotalFreeMemPercRApp | Out-File -Encoding UTF8 -FilePath \"H:\\sdassistence\\tmp\\Util.tmp\"");
commands.println("exit");
commands.close();
while(!file.exists() & !file.canWrite()){}
Thread.sleep(1000);
FileReader fr = new FileReader(file);
BufferedReader in = new BufferedReader(fr);
String test[] = in.readLine().split(";");
System.out.println(test[0] + " " + test[1] + " " + test[2]);
fr.close();in.close();process.destroy();
}
}
public static void main(String[] args) throws LoginException, IOException, InterruptedException {
getSystemAvarageUtil("DesktopServer","AppServer","XXXXXX");
}
}

Related

Running cscript //U (Unicode) from Java fails on some Windows versions

I have a Java application that runs cscript.exe to execute a simple VBScript. For illustration purposes, the content of the script (test.vbs) is this:
Wscript.Echo "ready"
The simplified Java code looks like this:
import java.io.*;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
public class Test
{
static boolean useUnicode = false;
public static void main(String args[]) throws Exception
{
String unicodeOpt = useUnicode ? "//U" : "";
Charset charset = useUnicode ? StandardCharsets.UTF_16LE : Charset.defaultCharset();
Process p = Runtime.getRuntime().exec("cscript " + unicodeOpt + " //NoLogo test.vbs");
InputStream pin = p.getInputStream();
BufferedReader input = new BufferedReader(new InputStreamReader(pin, charset));
System.out.println("Available: " + pin.available());
System.out.println("Output: " + input.readLine());
}
}
This works fine if useUnicode is false:
Available: 7
Output: ready
However when useUnicode is true (this passes //U to cscript) it does not work; the input stream returned by p.getInputStream() reports 0 bytes available in this case:
Available: 0
Output: null
Running the same script from the command line (cscript //U //NoLogo test.vbs) works fine.
Why isn't this working when I run the same command from Java?
Edit: The problem only happens on some Windows machines. I have been able to reproduce it on Windows 7 and Windows 10 boxes, but not in all of them. Even in the cases where the problem can be reproduced with the Java code, running the script from the command line always works. I cannot find an explanation for this.
Try the following and look in the file 'output.txt' in the current directory for the output. NB I have now simplified the code and tested in Windows:
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.BufferedReader;
import java.io.Reader;
import java.io.Writer;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
public class Test {
public static void main(String args[]) throws Exception {
boolean useUnicode = false;
Charset charset = useUnicode ? StandardCharsets.UTF_16LE : Charset.defaultCharset();
String[] command = { "cscript.exe", "/u", "/nologo", "test.vbs" };
System.out.println("Executing command " + java.util.Arrays.toString(command));
ProcessBuilder pb = new ProcessBuilder(command);
pb.redirectErrorStream(true);
Process p = pb.start();
InputStream pin = p.getInputStream();
try (Reader input = new BufferedReader(new InputStreamReader(p.getInputStream(), charset));
Writer out = Files.newBufferedWriter(Path.of("output.txt"), charset)) {
input.transferTo(out);
}
}
}
Running in Windows:
C:\Users\User\AppData\Local\Temp>java Test
Executing command [cscript.exe, /u, /nologo, test.vbs]
C:\Users\User\AppData\Local\Temp>type output.txt
e a d y
Yes, naturally type cannot cope with Unicode, hence the weird output but the file opens properly in write.exe.

Cannot run python script from java jar

While working in IntelliJ everything worked but after I built jar it stopped. At first, it was just me forgetting to put it in jar build config, but now after making sure it is there, I still can't run it. These are ways I try:
InputStream script = mainView.class.getResourceAsStream("vizualize3D.py");
Process process = new ProcessBuilder("python3", "-").start() ;
Process p1 = Runtime.getRuntime().exec("python3 " + script);
Runtime rt = Runtime.getRuntime();
Process pr = rt.exec("python3 " + mainView.class.getResourceAsStream("vizualize3D.py"));
None of theme work despite having it in resources. I also tried to specify path to it in IntelliJ project and it works but only when run from IntelliJ after I start it from jar it doesn't.
Edit1:
For people that didn't understand py file is in jar file
None of the options involving you trying to execute "python3 "+script, and equivalents, will work. script is an InputStream, not a path on the file system, so simply concatenating it with a String will not give you anything meaningful. Additionally, since your script is not in its own file, and there's no simple way for the python interpreter to extract it, simply invoking it like this won't work.
What you can do, however, is to execute
python3 -
The - option here (at least on BSD-like systems) means "read from standard input, and interpret it as a script". Then, on the Java side, you can read the jar-packaged resource as a stream and pipe it to the python process's standard input.
For details on choosing the correct path for the resource, see How do I determine the correct path for FXML files, CSS files, Images, and other resources needed by my JavaFX Application?.
The following, in which the script is simply placed in the same package as the class, works for me:
PythonRunner.java:
package example.python;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
public class PythonRunner {
public static void main(String[] args) throws Exception {
String pythonInterpreter = "/usr/bin/python3" ; // default
if (args.length > 0) {
pythonInterpreter = args[0] ;
}
InputStream script = PythonRunner.class.getResourceAsStream("script.py");
Process pythonProcess = new ProcessBuilder(pythonInterpreter, "-")
.start();
// This thread reads the output from the process and
// processes it (in this case just dumps it to standard out)
new Thread(() -> {
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(pythonProcess.getInputStream()))) {
for (String line ; (line = reader.readLine()) != null ;) {
System.out.println(line);
}
} catch (IOException exc) {
exc.printStackTrace();
}
}).start();
// read the script from the resource, and pipe it to the
// python process's standard input (which will be read because
// of the '-' option)
OutputStream stdin = pythonProcess.getOutputStream();
byte[] buffer = new byte[1024];
for (int read = 0 ; read >= 0 ; read = script.read(buffer)) {
stdin.write(buffer, 0, read);
}
stdin.close();
}
}
script.py:
import sys
for i in range(10):
print("Spam")
sys.exit(0)
MANIFEST.MF
Manifest-Version: 1.0
Main-Class: example.python.PythonRunner
Eclipse layout:
Jar contents and result of running:
$ jar tf runPython.jar
META-INF/MANIFEST.MF
example/python/PythonRunner.class
example/python/script.py
$ java -jar runPython.jar
Spam
Spam
Spam
Spam
Spam
Spam
Spam
Spam
Spam
Spam
$

External python application is not running

Hi i just create a java application to run my python code externally. But it want giving me the out put.
this is my java code:-
package com.epatient;
import java.io.*;
public class InterpreterExample {
//static String workingDir = System.getProperty("user.dir");
//static String appDir = workingDir + "\\epatient\\epatient_prediction.py";
public static void main(String a[]){
try{
String appDir = "C:\\Users\\Thushara Kasun\\Documents\\juno\\serial.port\\epatient\\epatient_prediction.py";
System.out.println(appDir);
ProcessBuilder pb = new ProcessBuilder("python",appDir);
Process p = pb.start();
BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream()));
String ret = in.readLine();
System.out.println("value is : "+ret);
}catch(NumberFormatException e){e.printStackTrace();}
catch (IOException e) {e.printStackTrace();}
}
}
this is my python code :-
import sys
from sklearn.externals import joblib
import pandas as pd
import numpy as np
import csv
from sklearn.decomposition import PCA
import re
import psycopg2
import datetime
import time
con = None
bio_data = None
heart_rate = None
so2_data = None
temp_data = None
bp_data = None
try:
con = psycopg2.connect(database='Epatient_user_1', user='postgres', password='root')
cur = con.cursor()
...#database access codes omited
model_name = 'trained_model'
est = joblib.load(model_name)
predictions = est.predict(data)
#predictions
# <codecell>
#sys.stdout.write(str(int(predictions[0])))
#sys.stdout.flush()
#print int(predictions[0])
ts = time.time()
st = datetime.datetime.fromtimestamp(ts).strftime('%Y-%m-%d %H:%M:%S')
#print st
cur.execute('INSERT INTO patient_status (STATUS,TIME,PROCESSED) VALUES (' + str(int(predictions[0])) + ',\''+ st + '\',0);')
con.commit()
except psycopg2.DatabaseError, e:
print 'Error %s' % e
sys.exit(1)
finally:
if con:
con.close()
sys.stdout.write(str(int(predictions[0])))
sys.stdout.flush()
#print int(predictions[0])
Java out put is just value is : null
there is no problem with the python code it is working perfectly. i just want to print a Boolean which is in a string format. simultaneously i need to update that value in my local postgresql database(via python code, which is working individually). simply the python code is not executing by my java application. Kindly help me on this or give me a alternative way to resolve this issue.
I think that your Java code is Ok, then try to change your Python script.
Please, would you be so kind to change the line print int(predictions[0]) with:
sys.stdout.write(str(predictions[0]))
sys.stdout.flush()
sys.stdout will print data to console outputstream
and just for testing, put the absolute path of your script in the ProcessBuilder constructor:
String appDir = "C:\\my\\full\\path\\to\\script.py";
ProcessBuilder pb =
new ProcessBuilder("python", appDir);
Process p = pb.start();
....

How to invoke a Linux shell command from Java

I am trying to execute some Linux commands from Java using redirection (>&) and pipes (|). How can Java invoke csh or bash commands?
I tried to use this:
Process p = Runtime.getRuntime().exec("shell command");
But it's not compatible with redirections or pipes.
exec does not execute a command in your shell
try
Process p = Runtime.getRuntime().exec(new String[]{"csh","-c","cat /home/narek/pk.txt"});
instead.
EDIT::
I don't have csh on my system so I used bash instead. The following worked for me
Process p = Runtime.getRuntime().exec(new String[]{"bash","-c","ls /home/XXX"});
Use ProcessBuilder to separate commands and arguments instead of spaces. This should work regardless of shell used:
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
public class Test {
public static void main(final String[] args) throws IOException, InterruptedException {
//Build command
List<String> commands = new ArrayList<String>();
commands.add("/bin/cat");
//Add arguments
commands.add("/home/narek/pk.txt");
System.out.println(commands);
//Run macro on target
ProcessBuilder pb = new ProcessBuilder(commands);
pb.directory(new File("/home/narek"));
pb.redirectErrorStream(true);
Process process = pb.start();
//Read output
StringBuilder out = new StringBuilder();
BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line = null, previous = null;
while ((line = br.readLine()) != null)
if (!line.equals(previous)) {
previous = line;
out.append(line).append('\n');
System.out.println(line);
}
//Check result
if (process.waitFor() == 0) {
System.out.println("Success!");
System.exit(0);
}
//Abnormal termination: Log command parameters and output and throw ExecutionException
System.err.println(commands);
System.err.println(out.toString());
System.exit(1);
}
}
Building on #Tim's example to make a self-contained method:
import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
import java.util.ArrayList;
public class Shell {
/** Returns null if it failed for some reason.
*/
public static ArrayList<String> command(final String cmdline,
final String directory) {
try {
Process process =
new ProcessBuilder(new String[] {"bash", "-c", cmdline})
.redirectErrorStream(true)
.directory(new File(directory))
.start();
ArrayList<String> output = new ArrayList<String>();
BufferedReader br = new BufferedReader(
new InputStreamReader(process.getInputStream()));
String line = null;
while ( (line = br.readLine()) != null )
output.add(line);
//There should really be a timeout here.
if (0 != process.waitFor())
return null;
return output;
} catch (Exception e) {
//Warning: doing this is no good in high quality applications.
//Instead, present appropriate error messages to the user.
//But it's perfectly fine for prototyping.
return null;
}
}
public static void main(String[] args) {
test("which bash");
test("find . -type f -printf '%T#\\\\t%p\\\\n' "
+ "| sort -n | cut -f 2- | "
+ "sed -e 's/ /\\\\\\\\ /g' | xargs ls -halt");
}
static void test(String cmdline) {
ArrayList<String> output = command(cmdline, ".");
if (null == output)
System.out.println("\n\n\t\tCOMMAND FAILED: " + cmdline);
else
for (String line : output)
System.out.println(line);
}
}
(The test example is a command that lists all files in a directory and its subdirectories, recursively, in chronological order.)
By the way, if somebody can tell me why I need four and eight backslashes there, instead of two and four, I can learn something. There is one more level of unescaping happening than what I am counting.
Edit: Just tried this same code on Linux, and there it turns out that I need half as many backslashes in the test command! (That is: the expected number of two and four.) Now it's no longer just weird, it's a portability problem.

Better way of opening a Document from Java?

I've been using the following code to open Office Documents, PDF, etc. on my windows machines using Java and it's working fine, except for some reason when a filename has embedded it within it multiple contiguous spaces like "File[SPACE][SPACE]Test.doc".
How can I make this work? I'm not averse to canning the whole piece of code... but I'd rather not replace it with a third party library that calls JNI.
public static void openDocument(String path) throws IOException {
// Make forward slashes backslashes (for windows)
// Double quote any path segments with spaces in them
path = path.replace("/", "\\").replaceAll(
"\\\\([^\\\\\\\\\"]* [^\\\\\\\\\"]*)", "\\\\\\\"$1\"");
String command = "C:\\Windows\\System32\\cmd.exe /c start " + path + "";
Runtime.getRuntime().exec(command);
}
EDIT: When I run it with the errant file windows complains about finding the file. But... when I run the command line directly from the command line it runs just fine.
If you are using Java 6 you can just use the open method of java.awt.Desktop to launch the file using the default application for the current platform.
Not sure if this will help you much... I use java 1.5+'s ProcessBuilder to launch external shell scripts in a java program. Basically I do the following: ( although this may not apply because you don't want to capture the commands output; you actually wanna fire up the document - but, maybe this will spark something that you can use )
List<String> command = new ArrayList<String>();
command.add(someExecutable);
command.add(someArguemnt0);
command.add(someArgument1);
command.add(someArgument2);
ProcessBuilder builder = new ProcessBuilder(command);
try {
final Process process = builder.start();
...
} catch (IOException ioe) {}
The issue may be the "start" command you are using, rather than your file name parsing. For example, this seems to work well on my WinXP machine (using JDK 1.5)
import java.io.IOException;
import java.io.File;
public class test {
public static void openDocument(String path) throws IOException {
path = "\"" + path + "\"";
File f = new File( path );
String command = "C:\\Windows\\System32\\cmd.exe /c " + f.getPath() + "";
Runtime.getRuntime().exec(command);
}
public static void main( String[] argv ) {
test thisApp = new test();
try {
thisApp.openDocument( "c:\\so\\My Doc.doc");
}
catch( IOException e ) {
e.printStackTrace();
}
}
}

Categories