Using ProcessBuilder to read/write to telnet process - java

I am trying to read/write values from/to telnet process by means of ProcessBuilder.
public static void main(String[] args) {
try {
telnetProcess = new ProcessBuilder("C:\\Windows\\System32\\telnet.exe","x.x.x.x").start();
telnetInputReader = new BufferedReader(new InputStreamReader(telnetProcess.getInputStream()));
telnetOuputWriter = new BufferedWriter(new OutputStreamWriter(telnetProcess.getOutputStream()));
expectPattern("login:");
sendCmd("user");
expectPattern("password:");
sendCmd("pwd");
expectPattern("switch>#");
sendCmd("exit");
expectPattern("Connection to host lost");
} catch (IOException ex) {
System.out.println("Exception : " + ex);
}
}
I got the following error
java.io.IOException: Cannot run program "C:\Windows\System32\telnet.exe": CreateProcess error=2, The system cannot find the file specified
I tried to change the file path to unix formatted style like C:/Windows/System32/telnet.exe and no luck. (Though I expected it to not to work). Then copied the telnet.exe from it's location to some other user's home directory and I was not getting any errors. (???)
But, I didn't see the output as expected. I didn't get any response from the process and the code exited.
public static void sendCmd(String cmd) {
System.out.println(cmd);
try {
telnetOuputWriter.write(cmd + "\n", 0, cmd.length());
} catch (IOException ex) {
Logger.getLogger(TelnetProcessHandler.class.getName()).log(Level.SEVERE, null, ex);
}
}
public static String expectPattern(String pattern) {
String cmdResponse = "";
try {
String line = "";
// Always getting 'null' here
while ((line = telnetInputReader.readLine()) != null) {
System.out.println(line);
cmdResponse += line;
if (line.contains(pattern)) {
break;
}
}
} catch (IOException ex) {
System.out.println("ex : " + ex);
}
return cmdResponse;
}
What is wrong in this ? Then, one other query. I have tried using PrintWriter for writing to process which in turn has BufferedWriter in it, like,
telnetOuputWriter = new PrintWriter(new BufferedWriter(new OutputStreamWriter(telnetProcess.getOutputStream())));
Is this fine to use PrintWriter in this context ?
Note : Due to some reasons, I would like to stick with using telnet by means of process, not with Socket or TelnetClient or expect4j.

The telnet program does not use the standard input and output streams to communicate with the user, it needs to use the console device directly. You'll have to find an alternative way of doing what you're trying to do.
For example you could use a Java library that implements the telnet protocol. See this question for example: Open source Telnet Java API

Related

Jar file not accepting huge string in java

What is the best way of passing a string (arg1 in case of code below) with about 800K characters (yes, that's a huge number) to a java jar. Following is the code I am using to invoke the jar file:
p = Runtime.getRuntime().exec(jrePath+"/bin/java -jar C:/folder/myjar.jar methodName" + arg1);
ALternately, how can I create a jar file to accept one String input and one byte[] input in main{ in void main(String args[])}
Or any other ideas? The requirement is to somehow pass the huge String/byte[] of String to a java jar file that I am creating
As mentioned in this question, there is a maximum argument length set by the operating system. Seeing as this argument is 800K characters, its fairly safe to say that you have exceeded this max value on most computers. To get around this, you can write arg1 to a temp file using the built in API:
final File temp;
try {
temp = File.createTempFile("temp-string", ".tmp");
} catch (final IOException e){
//TODO handle error
return;
}
try (final BufferedWriter writer = new BufferedWriter(new FileWriter(temp))) {
writer.write(arg1);
} catch (final IOException e){
//TODO handle error
return;
}
try {
// run process and wait for completion
final Process process = Runtime.getRuntime().exec(
jrePath + "/bin/java -jar C:/folder/myjar.jar methodName " +
temp.getAbsolutePath());
final int exitCode = process.waitFor();
if (exitCode != 0) {
//TODO handle error
}
} catch (final IOException | InterruptedException e){
//TODO handle error
return;
}
if (!file.delete()) {
//TODO handle error
}

JNA - How to get processID by .exe

So I'm using "findWindow" atm to get the processID, but lets say instead of using find window for example to get "Call Of Duty Black Ops", I want to straight up get the processID with the process name itself which is "BlackOps.exe". How would I do this?
here is my code to find proccess id with java "
public static void main(String[] args) {
String taskListCommand = System.getenv("windir") + "\\system32\\" + "tasklist.exe";
try {
final Process p = Runtime.getRuntime().exec(taskListCommand);
BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line;
try {
while ((line = input.readLine()) != null) {
if (line.contains("BlackOps.exe")) {
System.out.println(line);
PID = (line.split("\\s+"))[1];
System.out.println("PID = " + PID);
break;
}
}
input.close();
} catch (IOException e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
}
}
#using<System.dll>
using namespace System;
using namespace System::Diagnostics;
using namespace System::ComponentModel;
int main()
{
// Get the current process.
Process^ currentProcess = Process::GetCurrentProcess();
// Get all processes running on the local computer.
array<Process^>^localAll = Process::GetProcesses();
// Get all instances of Notepad running on the local computer.
// This will return an empty array if notepad isn't running.
array<Process^>^localByName = Process::GetProcessesByName("notepad");
// Get a process on the local computer, using the process id.
// This will throw an exception if there is no such process.
Process^ localById = Process::GetProcessById(1234);
// Get processes running on a remote computer. Note that this
// and all the following calls will timeout and throw an exception
// if "myComputer" and 169.0.0.0 do not exist on your local network.
// Get all processes on a remote computer.
array<Process^>^remoteAll = Process::GetProcesses("myComputer");
// Get all instances of Notepad running on the specific computer, using machine name.
array<Process^>^remoteByName = Process::GetProcessesByName( "notepad", "myComputer" );
// Get all instances of Notepad running on the specific computer, using IP address.
array<Process^>^ipByName = Process::GetProcessesByName( "notepad", "169.0.0.0" );
// Get a process on a remote computer, using the process id and machine name.
Process^ remoteById = Process::GetProcessById( 2345, "myComputer" );
}
The code above is written by microsoft itself, you can see the full answer here:
https://msdn.microsoft.com/en-us/library/z3w4xdc9(v=vs.110).aspx?cs-save-lang=1&cs-lang=cpp#code-snippet-2

Java runtime exec getInputStream when process pauses

I am creating a wrapper for a executable that runs on the windows command line. The executable takes a few commands then attempts to connect to another device. then it outputs and ERROR! or Ready For "Device Name" i do not get this message until the app exits. The problem is this app is a tunnel allowing me to run telnet on the external box but i need to make sure the Device is ready this is my code.
public void startUDPTunnel() {
//TODO Pull Amino serial number from webportal
Properties prop = new Properties();
InputStream inConfig = getClass().getClassLoader().getResourceAsStream("config.properties");
try {
prop.load(inConfig);
} catch (IOException e) {
System.out.println(e.getMessage());
}
String server = prop.getProperty("server");//config.GetProp("server");
System.out.println(server);
String port = prop.getProperty("port");//config.GetProp("port");
System.out.println(port);
String location = prop.getProperty("location");//config.GetProp("location");
System.out.println(location);
String url = prop.getProperty("URL");
System.out.println(url);
String input = "";
try {
input = getSerial(url);
System.out.println(input);
Process p = Runtime.getRuntime().exec(location+"udptunnel.exe -c 127.0.0.1 23 "+input+" "+server+" "+port+" 127.0.0.1 23");
threadSleep();
BufferedReader in = new BufferedReader(
new InputStreamReader(p.getInputStream()));
String line = null;
while ((line = in.readLine()) != null) {
if(line.equals("ERROR!")){
System.out.println("There was an ERROR");
}
if(line.equals("Ready for \""+input+"\"")){
System.out.println("Load Telnet");
}
}
p.destroy();
} catch (IOException e) {
e.printStackTrace();
}
}
Sorry there is a lot of debug code left in this function.
EDIT
OK I am pretty sure know what the issue is bufferReader.readLine() requires a \n or \r or just hangs is there anyway to watch the stream with out the buffer?
You should use a ProcessBuilder, and then use redirectErrorStream(). I think this will cause stdout of the process to be unbuffered. And even if it doesn't, you'll only have to read from one InputStream to get both stdout and stderr.
I have figured out my problem the applications that i am executing with java do not have a EOL at the end of the line in fact they just hang on the line For example telnet waits for the username then the password. i am not sure this is proper but it works and is what i am going to use for now
while((i=br.read())!=-1){
ch += (char)i;
}
This outputs every char as they come in when then i just make sure the string contains what i am looking for!

Error handling in java

Am running .exe file from java code using ProcessBulider, the code I have written is given below. The .exe file takes Input.txt(placed in same directory) as input and provide 3 output file in same directory.
public void ExeternalFileProcessing() throws IOException, InterruptedException {
String executableFileName = "I:/Rod/test.exe;
ProcessBuilder processBuilderObject=new ProcessBuilder(executableFileName,"Input.txt");
File absoluteDirectory = new File("I:/Rod");
processBuilderObject.directory(absoluteDirectory);
Process process = processBuilderObject.start();
process.waitFor();
}
this process is working fine by call ExeternalFileProcessing(). Now am doing validation process, If there is any crash/.exe file doesn't run, I should get the error message how can I get error message?
Note: It would be better that error message be simple like run successful/doesn't run successful or simply true/false, so that I can put this in If condition to continue the remaining process.
You can add exception handlers to get the error message.
public void externalFileProcessing() {
String executableFileName = "I:/Rod/test.exe";
ProcessBuilder processBuilderObject = new ProcessBuilder(
executableFileName, "Input.txt");
File absoluteDirectory = new File("I:/Rod");
processBuilderObject.directory(absoluteDirectory);
try {
Process process = processBuilderObject.start();
process.waitFor();
// this code will be executed if the process works
System.out.println("works");
} catch (IOException e) {
// this code will be executed if a IOException happens "e.getMessage()" will have an error
e.printStackTrace();
} catch (InterruptedException e) {
// this code will be executed if the thread is interrupted
e.printStackTrace();
}
}
But it would be better to handle it in the calling function by put a try catch handler in the calling function and handling it there.
Is it a third party .exe or do you have access to its sources? If so, you could work with basic System outputs (for example couts to the console).
Those outputs can be redirected to your java app using something like this:
InputStream is = process.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line = "";
while ((line = br.readLine()) != null) {
if(line.equals("something")) {
// do something
}
}
br.close();
This is how i do things like that and it works very well in general. But i must admit, that i can not say/garuantee, that this is THE way to do it. A more advanced approach might be the use of StreamGobbler (see Listing 4.5) to handle the outputs of the .exe.
Let me know if it helped you or not.

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