I'm trying to integrate with a legacy system. The legacy system uses dialog windows to report errors. It have no return codes at all except for the dialog windows. I start the legacy system with Runtime.exec().
Is there a way to detect if the executed program has spawned dialog windows or any other graphical interface? This solution is done in Windows and the executed program is an exe.
If the legacy system report errors in console, is possible get your erros.
Simply take the inputstream of error and do your reading.
Like this:
Runtime rt = Runtime.getRuntime();
Process proc = rt.exec(cmd);
// any error message?
InputStream error = proc.getErrorStream();
InputStreamReader isr = new InputStreamReader(error);
BufferedReader br = new BufferedReader(isr);
String line=null;
while ( (line = br.readLine()) != null)
System.out.println(" ERROR >" + line);
I recommend to read: Runtime.exec() quirks
Hope this help.
You can use this JNA snippet to poll for windows started by your process.
AFAIK, you can only get the standard and error output streams from a process using the Java Process API.
So the solution i did, is to use the snippet code that #Gerrett Hall linked to. That snippet code check the active window before i run the command and save the name.
Then after a vile if the command have not returned check if the active window have changed. if it have, kill the process(Alt. send a return key global).
To get the info from the dialog i could use Ctrl + C to copy the content of the dialog and reading the paste buffer to copy the message in to the log. Have not figured out that part yet.
And yes this is a ugly hack but so is the legacy system to.
Related
I tested this code(below) on several different linux boxes(4+) and it worked fine. However, on one linux box I ran into an issue with readline() hanging for the error inputStream(errorStream). This stream should be empty so I suspected that box was not writing out a line terminator to the errorStream for the error. I changed my code to use read() instead of readline()...but read() also hung.
I tried retrieving the input inputStream first, and that worked and there was no hangs with readline()/read() for the error inputstream. I could not do this since I needed to obtain possible errors first. Appearing to be a deadlock, I was able to resolve this by having each inputstream read from it's own thread. Why did I only see this issue on one box? Is there a kernel setting or some other setting specific to this box that could have caused this?
ProcessBuilder processBuilder = new ProcessBuilder()
try
{
Process processA = null;
synchronized (processBuilder)
{
processBuilder.command("/bin/sh","-c"," . /Home/SomeScript.ksh");
processA = processBuilder.start();
}
inputStream = processA.getInputStream();
reader = new BufferedReader(new InputStreamReader(inputStream));
errorStream = processA.getErrorStream();
errorReader = new BufferedReader(new InputStreamReader(errorStream));
String driverError;
while ((driverError = errorReader.readLine()) != null)
{
//some code
}
Why did I only see this issue on one box?
Most likely because of something in the script that is being run ... and its interactions with its environment (e.g. files, environment variables, etc)
Is there a kernel setting or some other setting specific to this box that could have caused this?
It is possible but unlikely that it is a kernel setting. It might be "something else". Indeed, it has to be "something" outside of the Java application that is to blame, at least in part.
I suggest you do the following temporarily (at least):
ProcessBuilder processBuilder = new ProcessBuilder();
processBuilder.command("/bin/sh","-c"," . /Home/SomeScript.ksh");
processBuilder.redirectErrorStream(true);
processA = processBuilder.start();
inputStream = processA.getInputStream();
reader = new BufferedReader(new InputStreamReader(inputStream));
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
System.out.println("Return code is " + processA.exitValue());
That way you can see what all of the output is.
There should not be a problem if the external process fails to put a newline at the end of the last line. The Java process will see an EOF on the input stream, and the BufferedReader will return what characters it has ... and return null on the next call.
Another possibility is that the external process is blocking because it is trying to read from its standard input.
UPDATE
The redirectErrorStream also resolved the issue, but I need the error stream separate.
OK so if it did (reliably) solve the problem then that (most likely) means that you have to read the external processes stdout and stderr streams in parallel. The simple way to do is to create 2 threads to read and buffer the two streams separately. For example: Capturing stdout when calling Runtime.exec
(Your problem is due to the fact that pipes have a finite buffering capacity. The external problem is most likely alternating between writing stuff to stdout and stderr. If it tries to write to one of the pipes when that pipe is "full", it will block. But if your application is reading all of the other pipe (to EOF) before it reads the blocked pipe, then everything will deadlock. The fact that the external process is stuck in PIPE_W state is more evidence for this explanation.
One possible reason that you are seeing different behaviour on different systems is that the amount of buffering in a pipe is system dependent. But it could also be due to differences in what the external process is doing; e.g. its inputs.)
You are running OS specific commands in a script, any one could be holding the error output. You can avoid this by discarding the errors, but that is unlikely to be a good idea.
I would check the version of the OS are the same and whether you have any significant differences in the command you run in the script. If this doesn't help, take out commands from the script until it starts working. I assume an empty script doesn't do this.
I am trying to call a python script from a java/tomcat6 webapp. I am currently using the following code:
Process p = Runtime.getRuntime().exec("python <file.py>");
InputStream in = p.getInputStream();
InputStreamReader isr = new InputStreamReader(in);
BufferedReader b = new BufferedReader(isr);
logger.info("PYTHON OUTPUT");
String line = null;
while ( (line = b.readLine()) != null){
logger.info(line);
}
p.waitFor();
logger.info("COMPLETE PYTHON OUTPUT");
logger.info("EXIT VALUE: "+p.exitValue());
I can't really see any output in the catalinia.out file from the python script and using an adapter library like jython is not possible as the script relies on several machine learning libraries that need python's Numpy module to work.
Help?
The explanation is probably one (or more) of following:
The command is failing and writing error messages to its "stderr" fd ... which you are not looking at.
The command is failing to launch because the command name is incorrect; e.g. it can't be found on $PATH.
The command is trying to read from its stdin fd ... but you haven't provided any input (yet).
It could be a problem with command-line splitting; e.g if you are using pathnames with embedded spaces, or other things that would normally be handled by the shell.
Also, since this is python, this could be a problem with python-specific environment variables, the current directory and/or the effective user that is executing the command.
How to proceed:
Determine if the python command is actually starting. For instance. "hack" the "" to write something to a temporary file on startup.
Change to using ProcessBuilder to create the Process object. This will give you more control over the streams and how they are handled.
Find out what is going to the child processes "stderr". (ProcessBuilder allows you to redirect it to "stdout" ...)
I am working on a java based desktop application. One requirement is that if application is running and user try to start the application again it should do something like show some alert etc.
I used file for this, when user run the app it add some text into a file and save it somewhere on the local system and when user try to run the app again i check the file and handle the situation accordingly, but there are some issue with this, like if application is abnormally terminated i am not able to remove that file and in that case when user tries to run the app system shows alert that application is already running but actually app terminated abnormally.
I did some R&D and found that i can read windows task manager list and then i can get and check my app if it is running. it was working fine but during testing i got an issue i-e there is a software/utility in windows named "tasklist" go to "start --> run" and type tasklist it will show you the task list. if this utility is not installed on your system or removed/corrupted for some reason then this will not work and same issue occur that user can start the application more then one time. Here is code to access the taskmanager items
Process p = Runtime.getRuntime().exec(
System.getenv("windir") + "/system32/" + "tasklist.exe");
BufferedReader input = new BufferedReader(new InputStreamReader(
p.getInputStream()));
while ((line = input.readLine()) != null) {
/*
Make the comparison here and show alert.
*/
}
Question: What is a good way to check if the app is already running? I am using Java for application, and advanced installer to create the installer of the application.
Launch the app. with Java Web Start and use the SingleInstanceService. See the demo. of the SingleInstanceService for (demo. and) example code.
am using .. advanced installer to create the installer
Note that JWS:
Is also an application installer. So I am suggesting this route as an alternative to using 'advanced installer'.
Is provided by the makers of Java (Sun/Oracle).
Check out http://ss64.com/nt/wmic.html
and try
String line;
try {
Process proc = Runtime.getRuntime().exec("wmic.exe");
BufferedReader input = new BufferedReader(new InputStreamReader(proc.getInputStream()));
OutputStreamWriter oStream = new OutputStreamWriter(proc.getOutputStream());
oStream .write("process where name='THE NAME OF YOUR PROCESS.exe'");
oStream .flush();
oStream .close();
while ((line = input.readLine()) != null) {
System.out.println(line);
}:
input.close();
} catch (IOException ioe) {
ioe.printStackTrace();
}
Courtesy:How to detect via Java whether a particular process is running under Windows?
I need to read the output of a process running on IBM j9 (emulator JVM to windows mobile). I tried this:
Process p = Runtime.getRuntime().exec("j9.exe");
BufferedReader br = new BufferedReader(new InputStreamReader(
p.getInputStream()));
String stringLog;
while ((stringLog = br.readLine()) != null) {
System.out.println(stringLog + "\n");
}
But it didn't work because it returned a new instance of j9.exe, not the existing process.
I need to get all messages that are being logged to System.out from j9console (of the existing process). How would I go about doing that?
It is not possible using pure Java. You would have to write a native library that makes low level OS function calls, and expose the library to Java via JNI. Even at the native level, the OS may not have system calls that provide this capability, depending on the OS -- it is an unusual task you are asking for, something that is usually done only by debuggers. E.g. gdb.
You would have to arrange for the process to write its output to a named pipe, and have Java read that pipe. Hope you're not on Windows!
I'm making an update function for my project, it's working great, until i want it to restart, basically I download the new file and replace it with the old one, and then i want to run it again, now for some reason it doesn't wna run, and i don't get any error...
Here is the complete update class:
http://dl.dropbox.com/u/38414202/Update.txt
Here is the method i'm using to run my .jar file:
String currDir = new File("(CoN).jar").getAbsolutePath();
Process runManager = Runtime.getRuntime().exec("java -jar " + currDir);
It's not clear to me, why do you need to run the jar with a call to exec() . Given that you need to run the code in the .jar file from a Java program, you could simply run the main() method as defined in the jar's manifest, and capture its output - wherever that is.
Using exec() is OK when you need to call a program from the underlying operating system, but there are easier ways to do this if both the caller and the callee are Java programs.
Now, if your jar is gonna change dynamically and you need to update your program according to a new jar, there are mechanisms for reloading its contents, for instance take a look ath this other post.
The JavaDocs for the Process class specifically point out that if you don't capture the output stream of the Process and promptly read it that the process could halt. If this is the case, then you wouldn't see the process that you started run.
I think you have to capture the stream like this :
BufferedReader stdInput = new BufferedReader(new InputStreamReader(runManager.getInputStream()),8*1024);
BufferedReader stdError = new BufferedReader(new InputStreamReader(runManager.getErrorStream()));
// read the output from the command
String s = null;
System.out.println("Here is the standard output of the command:\n");
while ((s = stdInput.readLine()) != null) {
System.out.println(s);
}
The exec function doesn't automatically lookup into the PATH to start a process, so you have to pass the complete path for the java binary.
You can do that by using the java.home system property, see this answer: ProcessBuilder - Start another process / JVM - HowTo?
No one here seemed to help me, so I went to ask my friend and I had it almost right. It abiously required the string to be an array.
solution:
String[] cmd = {"java", "-jar", currDir};
try {
Runtime.getRuntime().exec(cmd);
} catch (IOException e1) {
e1.printStackTrace();
}