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.
Related
I am trying to call python within my java code. However I found that if I import numpy in my python code, this is my java code
Process pcs = Runtime.getRuntime().exec(cmd);
String result = null;
BufferedInputStream in = new BufferedInputStream(pcs.getInputStream());
BufferedReader br = new BufferedReader(new InputStreamReader(in));
System.out.println("\nExecuting python script file now.");
String lineStr = null;
while ((lineStr = br.readLine()) != null) {
result = lineStr;
}
br.close();
in.close();
System.out.println("done!");
System.out.println(result);
This is my python code:
import sys
import os
import numpy as np
a = sys.argv[1]
b = sys.argv[2]
print("hello world!")
print("%s * %s = %s"%(a,b,int(a)*int(b)))
Results if I don't include "import numpy as np":
10 * 11 = 110
Results if include "import numpy as np":
null
Any intuitive explanation?
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class Hello{
public static void main(String[] args)throws java.io.IOException{
Process pcs=Runtime.getRuntime().exec("python test.py 8 5");// in linux or unix use python3 or python
String result=null;
BufferedInputStream in = new BufferedInputStream(pcs.getInputStream());
BufferedReader br = new BufferedReader(new InputStreamReader(in));
System.out.println("\nExecuting python script file now.");
String lineStr = null;
while ((lineStr = br.readLine()) != null) {
result = lineStr;
}
br.close();
in.close();
System.out.println("done!");
System.out.println(result);
}
}
java code
compile:
javac Hello.java
run:
java Hello
#test.py
import sys
import os
import numpy as np
a = sys.argv[1]
b = sys.argv[2]
print("hello world!")
print("%s * %s = %s"%(a,b,int(a)*int(b)))
Have you got the right PYTHONPATH setup in your application? When you have import numpy as np in your code, you may be receiving back empty STDOUT and an ModuleNotFoundError in STDERR. You can confirm by extracting STDERR - or check with this code:
Launch.exe(cmd);
where Launch.java is:
public class Launch
{
/** Launch using FILE redirects */
public static int exec(String[] cmd) throws InterruptedException, IOException
{
System.out.println("exec "+Arrays.toString(cmd));
Path tmpdir = Path.of(System.getProperty("java.io.tmpdir"));
ProcessBuilder pb = new ProcessBuilder(cmd);
Path out = tmpdir.resolve(cmd[0]+"-stdout.log");
Path err = tmpdir.resolve(cmd[0]+"-stderr.log");
pb.redirectError(out.toFile());
pb.redirectOutput(err.toFile());
Process p = pb.start();
int rc = p.waitFor();
System.out.println("Exit "+rc +' '+(rc == 0 ? "OK":"**** ERROR ****")
+" STDOUT \""+Files.readString(out)+'"'
+" STDERR \""+Files.readString(err)+'"');
System.out.println();
return rc;
}
}
The fix for using numpy should be to access ProcessBuilder pb.environment() and set your PYTHONPATH for the subprocess before calling start()
I am trying to view the temperature table for my CPU on my Linux machine with Java. This bit of code will display the shell output for other commands, ls, cat file, but will not display watch sensors as it returns an interactive output. Is there a way I can convert it to plain text somehow?
Error: [/usr/bin/watch, sensors]
Error opening terminal: unknown.
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 tempapp{
public static void main (String args[]) throws IOException, InterruptedException {
//build command
List<String> commands = new ArrayList<String>();
commands.add("/usr/bin/watch");
//args
commands.add("sensors");
System.out.println(commands);
ProcessBuilder pb = new ProcessBuilder(commands);
pb.directory(new File("/home/ethano"));
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("\n success");
System.exit(0);
}
//weird termination
System.err.println(commands);
System.err.println(out.toString());
System.exit(1);
}
}
All that watch does is call the command it is given (sensors in this case) once every two seconds. You can simply have your application emulate this behaviour by calling /usr/bin/sensors in a for-loop once every two seconds (or however many times you need), therefore omitting the need to read interactive shell output.
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");
}
}
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();
....
Hi i am trying to run shell script from following code
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class ScriptTest {
public static void main(String[] args){
BufferedReader stdErr=null;
BufferedReader stdIn=null;
try{
System.out.println("In Script");
String[] commands= {"ls"};
Process process = Runtime.getRuntime().exec("/mobilityapps/testScript/testScript.sh");
stdIn= new BufferedReader(new InputStreamReader(process.getInputStream()));
stdErr = new BufferedReader(new InputStreamReader(process.getErrorStream()));
String inline= stdIn.readLine();
String errline =stdErr.readLine();
System.out.println("*Inline*"+inline);
System.out.println("*Errline*"+errline);
while(inline!=null){
System.out.println(inline);
inline=stdIn.readLine();
}
while(errline!=null){
System.out.println(errline);
errline=stdErr.readLine();
}
System.out.println("Process Exit Value: "+process.waitFor());
}catch(Exception excp){
excp.printStackTrace();
}
}
}
The script i am trying to call is
CURRDATE=`date '+%d%b%Y'`
TIMESTAMP=`date '+%H:%M'`
BASE_PATH=/mobilityapps/testScript
LOGFILE=${BASE_PATH}/logs_${CURRDATE}_${TIMESTAMP}.log
echo ${CURRDATE} ${TIMESTAMP}>>${LOGFILE}
All both the script and Java program are in the same directory.
When i run testScript.sh from PUTTY it runs fine
But when i run from Java program Process Exit Value is 255
Can anyone suggest the changes?
Try replacing the path
Runtime.getRuntime().exec("/mobilityapps/testScript/testScript.sh");
with
Runtime.getRuntime().exec("./mobilityapps/testScript/testScript.sh");
If you just use / at the begining, it means that it's a absolute path.
Using '.' indicates that is a relative path.