Process is not terminating Properly in java (Runtime) - java

I am executing CSharp Program with java Process by creating the .exe file but the process of that file is not responding with 0 exitCode.Errors are Empty.In Visual Studio it runs fine but with java, it creates problem.No output and no Errors, I am stuck in this Please help. I am using Java 7.
I am using Csc (inbuild compiler in .Net framework for windows) It is giving me dll reference error.Command is following
csc /nologo /r:D:/simulatorConfig/ArrayConversion.dll /out:D:\\apache-tomcat-7.0.64\\temp\\tmp749792186557790590.exe D:\\apache-tomcat-7.0.64\\temp\\tmp749792186557790590.cs
stream = new BufferedReader(new InputStreamReader(proc.getErrorStream()));
above is Error which is empty String.
code is here Please look at it.
public File compile(File sourceFile, LANGUAGE lang) throws InterruptedException, IOException, CompilerException, ConfigurationException {
String absolutePath = sourceFile.getCanonicalPath();
// System.out.println("absolutePath : " + absolutePath);
String destFile;
if (OsUtils.isWindows()) {
destFile = absolutePath.replace(lang.getFileExtension(), EXECUTABLE_FILE_SUFFIX);
} else {
destFile = absolutePath.replace(lang.getFileExtension(), "");
}
String compileCommand = generateCommand(absolutePath, destFile, lang);
logger.error("compileCommand : " + compileCommand);
// Compiles and create exe file for execution
Process proc = Runtime.getRuntime().exec(compileCommand);
// Wait for process to complete
int returnValue = proc.waitFor();
if (returnValue != 0) {
String errorMsg = getCompilerMessage(sourceFile, proc, lang);
throw new CompilerException(errorMsg);
}
proc.destroy();
return new File(destFile);
}
private String getCompilerMessage(File sourceFile, Process proc, LANGUAGE lang) throws IOException {
StringBuilder message = new StringBuilder();
BufferedReader stream = null;
String line = null;
switch (lang) {
case C:
case CPP:
// GNU C/CPP compiler prints compiler errors in standard errors
// tream
stream = new BufferedReader(new InputStreamReader(proc.getErrorStream()));
break;
case CSHARP:
// CSharp compiler prints compiler errors in standard output stream
stream = new BufferedReader(new InputStreamReader(proc.getErrorStream()));
break;
}
while ((line = stream.readLine()) != null) {
logger.error(line);
line = line.substring(line.indexOf(sourceFile.getName()) + (int) sourceFile.getName().length());
if (message.toString().isEmpty()) {
message.append(lang == LANGUAGE.CSHARP ? "Line" : "").append(line);
} else {
message.append("<br/>Line").append(line);
}
// message.append(line).append(SystemUtils.LINE_SEPARATOR);
}
stream.close();
return message.toString();
}
private String generateCommand(String sourceFile, String destFile, LANGUAGE lang) throws ConfigurationException {
// System.out.println("sourceFile : " + sourceFile + " -- destFile : " +
// destFile);
Configuration config = new PropertiesConfiguration("system.properties");
String cmd = "";
switch (lang) {
case C:
case CPP:
sourceFile = sourceFile.replace("\\", "\\\\");
destFile = destFile.replace("\\", "\\\\");
cmd = "g++ " + sourceFile + " -o " + destFile + " " + config.getString("C_CPP_HEADERFILE").trim();
break;
case CSHARP:
sourceFile = sourceFile.replace("\\", "\\\\");
destFile = destFile.replace("\\", "\\\\");
logger.error("Config Path : "+config.getString("MONO_PATH"));
if (OsUtils.isWindows()) {
cmd = "csc /nologo /r:" + config.getString("CS_HEADERFILE_WIN") + " /out:" + destFile + " " + sourceFile;
} else {
cmd = "/opt/mono/bin/mcs /reference:" + config.getString("CS_HEADERFILE") + " /out:" + destFile + " "
+ sourceFile;
}
break;
}
logger.info("Command :" + cmd);
return cmd;
}

When launching a command using Runtime#exec, you MUST consume the error and std streams in every case (not only when the return code is != 0), or else the internal buffers could/will get full and the subprocess will wait indefinitely until somebody consumes them.
The common symptom of this problem is an process that never return, making the whole seems to be deadlocked.
There are several ways to correct this, one the easiest is described here: https://docs.oracle.com/javase/7/docs/api/java/lang/ProcessBuilder.html#redirect-input.
Additionally, there seems to be an issue here:
// CSharp compiler prints compiler errors in standard output stream
stream = new BufferedReader(new InputStreamReader(proc.getErrorStream()));
break;
In the comment, you tell the compiler does output errors on stdout, but you are consuming the error stream.

There was .dll linking error in when I tried to do the same in command prompt with Demo files.By keeping .dll file and .exe file in the same directory it solved my purpose program was running Flawlessly with proper exit code (0).
So kept other .dll file in this path D:\apache-tomcat-7.0.64\temp\. and is fine.
The thumb rule says .dll and .exe should be in the same directoryeory

Related

Is it possible to delay or overwrite windows cannot find 'acrord32.exe' error message in java

I need to use both executable files of Adobe reader to open documents.
acrord32.exe for the users using adobe acrobat reader and acrobat.exe for the users using adobe acrobat pro.
I have used system parameters to get done the job.
But my problem is that whenever I use the acrobat.exe version this error message is coming.
After clicking ok then my pdf file opens from acrobat.exe.
So I just want to delay/overwrite/remove this message by using java...
Here is my code
public static void openPDF(Container container, String fileName) throws Exception, PrintException {
SystemParameterHome paramHome = (SystemParameterHome) container.getHomeForEntityBean();
try {
String pdfParameter = "PDF_COMMAND";
SystemParameterObject pdfCommand = paramHome.findByPrimaryKey(pdfParameter);
String command = pdfCommand.getStringValue();
Process proc = Runtime.getRuntime().exec(command + " \"" + fileName + "\"");
int exitVal = proc.waitFor();
if(exitVal != 0) {
System.out.println("exit value in if: "+ exitVal);
pdfParameter = "PDF_COMMAND_64";
pdfCommand = paramHome.findByPrimaryKey(pdfParameter);
command = pdfCommand.getStringValue();
Runtime.getRuntime().exec(command + " \"" + fileName + "\"");
throw new PrintException("There was an error in printing. Please contact a system administrator.");
}else {
System.out.println("exit value in else "+ exitVal);
}
}
catch (Exception e) {
e.printStackTrace();
}

Java Getting the Standard Output and Standard Error from a Seperate Process

I am starting a separate process in my Java program using ProcessBuilder This is were the process gets made:
Class klass=Program.class;
String[] output=new String[2];
String javaHome = System.getProperty("java.home");
String javaBin = javaHome +
File.separator + "bin" +
File.separator + "java";
String classpath = System.getProperty("java.class.path");
String className = klass.getCanonicalName();
ProcessBuilder builder = new ProcessBuilder(
javaBin, "-cp", classpath, className);
Process process = builder.start();
process.waitFor();
Program.class is the following:
public class Program {
public static void main(String[] args) {
System.out.println("Hi!");
}
I want the standard output to produce Hi!, and the standard error, if I were to, for example, not add a semicolon after System.out.println("Hi!") then the standard error would be:
Exception in thread "main" java.lang.Error: Unresolved compilation problem:
Syntax error, insert ";" to complete BlockStatements
at Program.main(Program.java:6)
So, how can I do this? Ideally, the program converts these into two strings.
Thanks
Start by taking a closer look at the Process class, it has an inputStream property, which is attached to the processes stdout. You can also use ProcessBuilder to redirect the stderr through the stdout to make life easier, using ProcessBuilder#redirectErrorStream(boolean)
You can write to the Process using its outputStream property (try not to think about it to much)...
Basically, you want to "read" the "output", via the inputStream and "write" to the "input" via the outputStream
Something like...
Class klass=Program.class;
String[] output=new String[2];
String javaHome = System.getProperty("java.home");
String javaBin = javaHome +
File.separator + "bin" +
File.separator + "java";
String classpath = System.getProperty("java.class.path");
String className = klass.getCanonicalName();
ProcessBuilder builder = new ProcessBuilder(
javaBin, "-cp", classpath, className);
builder.redirectErrorStream(true);
Process process = builder.start();
int in = -1;
InputStream is = process.getInputStream();
try {
while ((in = is.read()) != -1) {
System.out.println((char)in);
}
} catch (IOException ex) {
ex.printStackTrace();
}
int exitCode = process.waitFor();
System.out.println("Exited with " + exitCode);
as an example

Download an exe file and run

I've been trying to make it where I can download a .exe file from the web, read it, and write it to a file locally, and then execute.
URL url = new URL("http://www.ddlands.com/downloads/Calc.exe");
URLConnection c = url.openConnection();
BufferedReader br = new BufferedReader(new InputStreamReader(c.getInputStream()));
String line = "";
File file = new File("analbread"+".exe");
BufferedWriter bw = new BufferedWriter(new FileWriter(file));
while((line = br.readLine()) != null){
bw.write(line + "\n");
}
br.close();
bw.close();
Process r = Runtime.getRuntime().exec("analbread" + ".exe");
System.out.println(r.toString());
System.out.println("WORKS!");
Although I know that doesn't work due to using BufferedWriter, and i'm not sure if it runs the exe.
For the downloading part, you'll need to use binary read/write. See this for further details: Working unbuffered streams.
For the executing part, the problem is that the Runtime.exec()-method can't launch your executable file.
At least under Linux (I can't test it on Windows), you'll need the full path to the executable file (or use ./[file] when the file is in the same directory as your application) to be able to execute it.
Only giving the command works for executables which are part of your systems PATH-variable.
Have a look at ClickOnce: http://en.wikipedia.org/wiki/ClickOnce
We've used that succesfully.
Ive used the following with good results to run command line scripts. You can create a batch script that runs the executable or run it directly using the exec method - probably pass "cmd ". This opens a command prompt from which you can run anything.
public static void runScript(String batchFile, boolean waitForExit0, int retryTime)
{
try
{
String runString = "cmd /c start " + (waitForExit0?"/wait ":"") + "/MIN " + batchFile;
Process p = Runtime.getRuntime().exec(runString); // /c start /wait
while (true)
{
try
{
int exit = p.exitValue();
if (exit == 0)
{
System.out.println("completed: " + runString);
return;
}
}
catch(Exception e)
{
String s = "";
}
Thread.sleep(retryTime);
}
}
catch(Exception e)
{
String s = "";
}
}

how to write log file while starting services using java

hello everyone i created a java file,in that java i written a code for starting,stoping and restarring a windows service ,in that i want to create a log file and write output of window service as a console please if any one knows give suggestion
i used code for stoping service
public static void stopService(String serviceName) throws IOException,
InterruptedException {
String executeCmd = "cmd /c net stop \"" + serviceName + "\"";
Process runtimeProcess = Runtime.getRuntime().exec(executeCmd);
int processComplete = runtimeProcess.waitFor();
System.out.println("processComplete: " + processComplete);
if (processComplete == 1) {// if values equal 1 process failed
System.out.println("Service failed");
}
else if (processComplete == 0) {
System.out.println("Service Success");
}
}
Probably the best way to achieve this is Log4J. If you haven't used it before it can seem overbearing, but there are a lot of good tutorials out there to cherry pick from, should you need to. Put the LogFactory in your class definition and then pop lines like log.info.println("service starting"). The other keyword to keep an eye our for is FileAppender. (Sorry no better references, writing from my phone!)
The best solution is to use some logging API have a look at http://www.vogella.com/articles/Logging/article.html tutorial.
Or the other trivial option is to redirect the output of executing the command in some text File. Change the command
String executeCmd = "cmd /c net stop \" + serviceName + "\"+" >> "+ fileName".
In order to get the output of a command you can do this:
String lineSeparator = System.getProperty("line.separator");
stderr = runtimeProcess.getErrorStream();
stdout = runtimeProcess.getInputStream();
// clean up if any output in stdout
BufferedReader brCleanUp =
new BufferedReader(new InputStreamReader(stdout));
StringBuilder output = new StringBuilder();
String line;
while ((line = brCleanUp.readLine()) != null) {
output.append(line).append(lineSeparator);
}
brCleanUp.close();
// clean up if any output in stderr
brCleanUp =
new BufferedReader(new InputStreamReader(stderr));
StringBuilder error = new StringBuilder();
while ((line = brCleanUp.readLine()) != null) {
error.append(line).append(lineSeparator);
}
brCleanUp.close();
And now in output and error String you have the "standard output" and "standard error" of the process you executed.

Java Web Start deploy on Windows startup

I have a Java application that I'm about to begin to use Web Start to deploy. But a new demand has made me rethink this, as I'm now required to add a piece of functionality that allows the end user to select whether or not they'd like to run this program on startup (of Windows, not cross-platform). But I'd still like to shy away from making this run as a service. Is there any way that this can be accomplished using Web Start, or should I explore other options to deploy this? Thanks in advance.
It actually works to put a this in the jnlp-file:
<shortcut online="true">
<desktop/>
<menu submenu="Startup"/>
</shortcut>
But that still would only work with English windows versions. German is "Autostart", Spanish was "Iniciar" I think. So it causes basically the same headache as the way via the IntegrationService.
I have not tried it, but I wonder if you could use the new JNLP IntegrationService in combination with the javaws command line program. The idea being to programmatically create a shortcut in the Windows startup group (although that location is dependent on specific Windows version).
To get around the language problem for the Startup folder just use the registry. Here is some code that should work. This calls reg.exe to make registry changes.
public class StartupCreator {
public static void setupStartupOnWindows(String jnlpUrl, String applicationName) throws Exception {
String foundJavaWsPath = findJavaWsOnWindows();
String cmd = foundJavaWsPath + " -Xnosplash \"" + jnlpUrl + "\"";
setRegKey("HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Run", applicationName, cmd);
}
public static String findJavaWsOnWindows() {
// The paths where it will look for java
String[] paths = {
// first use the JRE that was used to launch this app, it will probably not reach the below paths
System.getProperty("java.home") + File.separator + "bin" + File.separator + "javaws.exe",
// it must check for the 64 bit path first because inside a 32-bit process system32 is actually syswow64
// 64 bit machine with 32 bit JRE
System.getenv("SYSTEMROOT") + File.separator + "syswow64" + File.separator + "javaws.exe",
// 32 bit machine with 32 bit JRE or 64 bit machine with 64 bit JRE
System.getenv("SYSTEMROOT") + File.separator + "system32" + File.separator + "javaws.exe",};
return findJavaWsInPaths(paths);
}
public static String findJavaWsInPaths(String[] paths) throws RuntimeException {
String foundJavaWsPath = null;
for (String p : paths) {
File f = new File(p);
if (f.exists()) {
foundJavaWsPath = p;
break;
}
}
if (foundJavaWsPath == null) {
throw new RuntimeException("Could not find path for javaws executable");
}
return foundJavaWsPath;
}
public static String setRegKey(String location, String regKey, String regValue) throws Exception {
String regCommand = "add \"" + location + "\" /v \"" + regKey + "\" /f /d \"" + regValue + "\"";
return doReg(regCommand);
}
public static String doReg(String regCommand) throws Exception {
final String REG_UTIL = "reg";
final String regUtilCmd = REG_UTIL + " " + regCommand;
return runProcess(regUtilCmd);
}
public static String runProcess(final String regUtilCmd) throws Exception {
StringWriter sw = new StringWriter();
Process process = Runtime.getRuntime().exec(regUtilCmd);
InputStream is = process.getInputStream();
int c = 0;
while ((c = is.read()) != -1) {
sw.write(c);
}
String result = sw.toString();
try {
process.waitFor();
} catch (Throwable ex) {
System.out.println(ex.getMessage());
}
if (process.exitValue() == -1) {
throw new Exception("REG QUERY command returned with exit code -1");
}
return result;
}
}

Categories