1

I am launching a process with Runtime.getRuntime().exec()

However, once Java reaches the end of the main() loop, java will not close, unless I destroy() the process first.

Problem with that is, I need the process to keep running after Java is closed.

I pretty much want to do this

public static void main(String args[]) {
  Runtime.getRuntime().exec("file.bat");
  // now I want java to close, and I want file.bat to keep running
}

I tried System.exit(), it will stop my main() loop, however I think a thread or something that was started by exec() keeps running, preventing java from closing. I can't even end it in Eclipse without first exiting file.bat

Why isn't it closing? And how would I fix it?

I couldn't find anything online, and I've been experimenting for a while, so I decided to ask you guys.

Thank you, -Alex Benoit

user255279
  • 21
  • 3
  • I don't think you can close java after making it open up some file, once you close that file the java should close with it. – SSpoke Mar 13 '14 at 21:11
  • @SSpoke yeah I'm worried that that may be the case. I'm thinking I might just make 2 files, one to launch the first one then close itself naturally, that would work, but it seems a bit unprofessional, plus I don't want to have to make another file for something like that. – user255279 Mar 13 '14 at 21:12
  • I'm not 100% sure but I think if you kill the java which opened the file, it will close that file with it. Not sure. Try it out make a loop in a bat file and kill the java.exe in task manager see if the bat closes too. – SSpoke Mar 13 '14 at 21:18
  • I believe this is a duplicate: http://stackoverflow.com/questions/931536/how-do-i-launch-a-completely-independent-process-from-a-java-program – Michael Minella Mar 13 '14 at 21:21
  • In the link Michael Minella posted something like `Runtime.getRuntime().exec("cmd /c start editor.exe");` will probably work since it will kill only cmd.exe but cmd.exe opened editor.exe which isn't connected to java or cmd.exe anymore. – SSpoke Mar 13 '14 at 21:24
  • @Michael Minella None of those solutions work. And the approved answer isn't even an answer, it was just a suggestion which should have been a comment. I already read it, and I don't know why it was approved. – user255279 Mar 13 '14 at 21:33
  • @SSpoke For some reason when you use cmd it has the same effect, even though CMD is already closed when the main loop ends, I even tried destroying it afterwards. Nothing. :\ – user255279 Mar 13 '14 at 21:34
  • did you use the `start` inside `cmd` too? – SSpoke Mar 13 '14 at 21:35
  • @SSpoke yeah I tried that – user255279 Mar 13 '14 at 21:36

3 Answers3

1

Figured it out. I'll share my code in case anyone else has the same question. I brought it down to 1 line.

Desktop.getDesktop().open(new File("C:\\Folder\\File"));
user255279
  • 21
  • 3
0

Launch the file with cmd for Windows Only

Older windows will probably have to use command.com instead

Runtime.getRuntime().exec("cmd /c start file.bat");

Using the start with /wait parameter waits until bat is finished without /wait it should work.

public class Command {

public static void main(String[] args) throws java.io.IOException, InterruptedException {
       String path = "C:\\DOCUME~1\\\USER\\DESKTOP";

       Process p = Runtime.getRuntime().exec("cmd /c start /wait " + path + "\\test.bat");

       System.out.println("Waiting for batch file ...");
       p.waitFor();
       System.out.println("Batch file done.");
   }
}

test.bat

@echo off
cls
:start
echo This is a loop
goto start

Use the command.com file to get short path name, since long path names don't get processed too well in start program.

Here is a sample I made download link below: https://www.mediafire.com/?mu7vht3e6tto698

Your problem may be that you are not on a Windows Administrator account you could try, But this requires you to type in your Administrator password which is very stupid.

Process p = Runtime.getRuntime().exec("runas /profile /user:Administrator \"cmd.exe /c start test.bat\"");
SSpoke
  • 5,656
  • 10
  • 72
  • 124
  • Sorry, read my reply to the comment. I just now replied. "For some reason when you use cmd it has the same effect, even though CMD is already closed when the main loop ends, I even tried destroying it afterwards. Nothing. :\" – user255279 Mar 13 '14 at 21:36
  • 1
    I have tested it right now and it works perfectly.. I will post test code. – SSpoke Mar 13 '14 at 21:39
  • I have added a sample download link, try it out https://www.mediafire.com/?mu7vht3e6tto698 – SSpoke Mar 13 '14 at 21:47
  • @SSpoke can you create a gist or paste it somewhere else? – OscarRyz Mar 13 '14 at 21:51
  • @SSpoke Wow you went all out. Thank you. However, when the cmd is told to launch a file that will continue running, it never gets passed "Waiting for batch file". I believe this is because of the /wait perimeter. However, if u remove that, then it would be the same as earlier. Yeah I tested your code without the /wait, and it still wont work. I think cmd may be holding on to the file that needs to keep running? But it doesn't make since b/c it gets past p.waitFor(). Augh this is confusing. – user255279 Mar 13 '14 at 21:53
  • The `test.bat` will keep running forever in my sample since, yeah no `/wait` of course maybe your issue has something to do with your windows account maybe it needs administrator powers? – SSpoke Mar 13 '14 at 21:56
  • @OscarRyz feel free to do so if you wish I don't understand anything about gist, I will post the test.bat into the topic as well. – SSpoke Mar 13 '14 at 21:56
  • @user255279 post your batch file into the question unless it's something sensitive of course. Actaully nevermind if my sample doesn't work then I doubt I can help. Maybe you have multiple java.exe's running and you think it didn't close lol :P – SSpoke Mar 13 '14 at 22:01
  • @SSpoke Nah, I'm running it in Eclipse :P – user255279 Mar 13 '14 at 22:33
  • 1
    Got it! Just learned about the Desktop class. Desktop.getDesktop().open(new File("filePathHere")); – user255279 Mar 13 '14 at 23:44
  • Good one, have to remember it as well. – SSpoke Mar 14 '14 at 00:47
0

This is a system dependent question. I am not sure if in Windows the parent process can terminate before the child. I believe this is true in linux.

As a guideline, you should call waitFor() on the process. However, on some systems, just doing so might not be enough. As pointed out in the javadoc, the out/err stream need to be properly purged (using the streams returned by getOutputStream() and getErrorStream()) because they could keep your process from completing. To do so, I found it most appropriate to use two separate threads, one purging the err stream, the other the out stream. The calling thread (main in your case), has to do the following:

  • start the external process;
  • start a thread to purge the out stream;
  • start a thread to purge the err stream;
  • call waitFor() on the calling thread (main).

I found the above approach very robust and easy to implement (if you are familiar with threads). Please use an ExecutorService for the threads.

Giovanni Botta
  • 9,626
  • 5
  • 51
  • 94