Is it possible to make java monitor if a cmd is done then runs another cmd?
For example...
btnStart.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent args)
{
try
{
String command = "cmd /c start "+DetectDrive+"\\starting.bat";
Process p = Runtime.getRuntime().exec(command);
}
catch (IOException e1)
{
e1.printStackTrace();
}
if(checkbox.isSelected())
{
try
{
String command = "cmd /c start "+DetectDrive+"\\Stage1.bat";
Process p = Runtime.getRuntime().exec(command);
}
catch (IOException e1)
{
e1.printStackTrace();
}
}
if(checkbox_1.isSelected())
{
try
{
String command = "cmd /c start "+DetectDrive+"\\Stage2.bat";
Process p = Runtime.getRuntime().exec(command);
}
catch (IOException e1)
{
e1.printStackTrace();
}
}
}
}
How do I make sure that once starting.bat finishing running in the cmd then if stage1 has been ticked then the stage1.bat will start running in the cmd???
And then after the stage1.bat finish running in the cmd, it will go backs to the code and check if stage2.bat is ticked, if it is, then stage2.bat will run.
Use Process.waitFor, but add /wait to your command to make then new process wait for the batch process to stop.
For example:
String command = "cmd /c start /wait Stage1.bat";
Process p = Runtime.getRuntime().exec(command);
p.waitFor();
The new process creates a new batch process and then terminates without the /wait.
Use Process.waitFor(). It will wait until the command ends.
Process has a waitFor method
from the javadoc:
Causes the current thread to wait, if necessary, until the process represented by this Process object has terminated.
This method returns immediately if the subprocess has already terminated.
If the subprocess has not yet terminated, the calling thread will be blocked until the subprocess exits.
Related
I have gone through few questions raised on how to achieve this.
I used process.waitFor() and /wait as mentioned here. The problem is by doing so it waits not just till the command is executed but until cmd prompt is closed (can be done by adding exit in the bat file). But I cannot modify bat file as its a Product file.
Runtime run = Runtime.getRuntime();
try {
String path = "C:/Folder/c.bat";
String executeCmd= "cmd /c start /wait "+path;
final Process process =run.exec(executeCmd);
process.waitFor();
System.out.println("did I wait?");
} catch (Exception e) {
e.printStackTrace();
}
How to make it wait only till the command is executed.
You can create a helper batch file with following content:
start /wait %1\c.bat
exit
Store this helper batch anywhere you want to.
Then start this helper batch file with the path to c.bat as its parameter.
Runtime run = Runtime.getRuntime();
try {
String pathToCBatch = "C:\\Folder\\";
String pathToHelperBatch = "c:/helperBatch.bat";
String executeCmd = "cmd /c start /wait " + pathToHelperBatch + " " + pathToCBatch;
final Process process = run.exec(executeCmd);
System.out.println(System.currentTimeMillis());
process.waitFor();
System.out.println(System.currentTimeMillis());
} catch (Exception e) {
e.printStackTrace();
}
I have also the same issue: "call a Batch file and wait until it's finished" (Windows PC). This solution works for me :
StringBuilder command = new StringBuilder("cmd /c start /wait C:\\script.bat");
// my script take 2 file as arguments
command.append(" ").append(inputFile);
command.append(" ").append(outputFile);
try {
final Process p = Runtime.getRuntime().exec(command.toString());
p.waitFor();
} catch (InterruptedException e) {
System.out.println(e);
}
also if the directory has space in it then the command wont work from string of arrey
so instead do this
File file = new File("E:\\NetBeans Projects\\Test.bat");
String[] command = {"cmd.exe", "/c", "start", file.getName() };
Runtime rt = Runtime.getRuntime();
Process pr = rt.exec(command , null , file.getParentFile());
dont work for me to exit cmd from java
i have come with a solution
i added "exit" in my .bat file at the end and it works now
example :
this is my "adservice.google.com.bat" bat file which dont exit after executing from java
netsh advfirewall firewall add rule name="adservice.google.com.bat" protocol=any dir=out action=block remoteip=2404:6800:4009:80f::2002,216.58.203.34
so i have to add "exit" in it , in the last line
netsh advfirewall firewall add rule name="adservice.google.com.bat" protocol=any dir=out action=block remoteip=2404:6800:4009:80f::2002,216.58.203.34
exit
this is basically what I am trying to do: I created a Process that simulates the command line. Like this:
private Process getProcess() {
ProcessBuilder builder = new ProcessBuilder("C:/Windows/System32/cmd.exe");
Process p = null;
try {
p = builder.start();
} catch (IOException e1) {
e1.printStackTrace();
}
return p;
}
Now I can "feed" this process with commands:
BufferedWriter p_stdin = new BufferedWriter(
new OutputStreamWriter(process.getOutputStream()));
try {
p_stdin.write("dir"); // Just a sample command
p_stdin.newLine();
p_stdin.flush();
} catch (IOException e) {
e.printStackTrace();
return "Failed to run " + fileName;
}
What I now would like to do is wait for the command, that is the subprocess of my process, to complete. How can I do that? I know that I can wait for processes with the waitFor() method, but what about a subprocess??
The dir command is not a subprocess, it is executed internal to cmd. However, this is not much relevant, anyway: from the perspective of Java any other command, which is launched in a subprocess, would behave the same.
To wait for the dir command to complete you must interpret the incoming stdout output from cmd and realize when the prompt was printed again. This is a quite brittle mechanism, though.
In any case, you currently don't consume cmd's stdout at all, which will cause it to block soon, never recovering.
In Java I want to execute a .lnk shortcut which it self executes a .exe file.
I run the executable like so:
String currentDir = new File(game.getGamePath()).getCanonicalPath();
ProcessBuilder processBuild = new ProcessBuilder(currentDir);
processBuild.command("cmd", "/c", "start" , currentDir);
Process = processBuild.start();
try {
Process.waitFor();
} catch (InterruptedException ex) {
Logger.getLogger(AuroraLauncher.class.getName()).log(Level.SEVERE, null, ex);
}
I want the waitFor() thread blocking method to wait until the actual executed application (.exe file) terminates before it continues not the shortcut. Is there a way to do this simply or do I have to somehow extract the .exe path from the .lnk? if so how would I do that?
"start" launches a separate process, so your process is done. But you can extract the actual executable path from the lnk file. take a look at this post.
Windows command "start" has an option /wait you must specify to tell him it has to wait for the end of the process.
This code run until you close notepad:
#Test
public void run() throws IOException {
String currentDir = new File(System.getProperty("user.home"),"desktop/notepad.lnk").getCanonicalPath();
ProcessBuilder processBuild = new ProcessBuilder(currentDir);
processBuild.command("cmd", "/c", "start","/wait", currentDir);
Process p= processBuild.start();
try {
p.waitFor();
} catch (InterruptedException ex) {
}
System.out.println("process terminated!");
}
Simpler than to parse the lnk file.
Your code certainly won't compile. You should fix it to compile and work as intended:
Process p = processBuild.start();
try {
p.waitFor(); // Ignoring the process result code.
} catch (InterruptedException ex) {
Logger.getLogger(AuroraLauncher.class.getName()).log(Level.SEVERE, null, ex);
}
In my Java program, I create a process that executes a command to run a batch file like this:
try {
File tempFile = new File("C:/Users/Public/temp.cmd");
tempFile.createNewFile();
tempFile.deleteOnExit();
setContents(tempFile, recipe.getText()); //Writes some user input to file
String cmd = "cmd /c start " + tempFile.getPath();
Process p = Runtime.getRuntime().exec(cmd);
int exitVal = p.waitFor();
refreshActionPerformed(evt);
} catch (InterruptedException ex) {
Logger.getLogger(mainFrame.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(mainFrame.class.getName()).log(Level.SEVERE, null, ex);
}
Now, what I would like to have happen is that the command
refreshActionPerformed(evt);
runs only after the batch file I called has finished executing. But right now, it runs immediately after the Command Prompt opens.
How do I fix this?
I manged to find the answer elsewhere. To keep the initial process open until the batch file finished all you need is "/wait"
Process p = Runtime.getRuntime().exec("cmd /C start /wait filepath.bat");
int exitVal = p.waitFor();
calling "cmd /c start" causes cmd to fire off another instance and exit immediately. Try taking out the "start" command.
The answer given is correct. I added that the window opened by the code needs to be closed manually.
Process p = Runtime.getRuntime().exec("cmd /C start /wait filepath.bat");
int exitVal = p.waitFor();
This is a followup question to my other question : Run bat file in Java and wait
The reason i am posting this as a separate question is that the one i already asked was answered correctly. From some research i did my problem is unique to my case so i decided to create a new question. Please go read that question before continuing with this one as they are closely related.
Running the proposed code blocks the program at the waitFor invocation. After some research i found that the waitFor method blocks if your process has output that needs to be proccessed so you should first empty the output stream and the error stream. I did those things but my method still blocks. I then found a suggestion to simply loop while waiting the exitValue method to return the exit value of the process and handle the exception thrown if it is not, pausing for a brief moment as well so as not to consume all the CPU. I did this:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Test {
public static void main(String[] args) {
try {
Process p = Runtime.getRuntime().exec(
"cmd /k start SQLScriptsToRun.bat" + " -UuserName -Ppassword"
+ " projectName");
final BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));
final BufferedReader error = new BufferedReader(new InputStreamReader(p.getErrorStream()));
new Thread(new Runnable() {
#Override
public void run() {
try {
while (input.readLine()!=null) {}
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
new Thread(new Runnable() {
#Override
public void run() {
try {
while (error.readLine()!=null) {}
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
int i = 0;
boolean finished = false;
while (!finished) {
try {
i = p.exitValue();
finished = true;
} catch (IllegalThreadStateException e) {
e.printStackTrace();
try {
Thread.sleep(500);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
}
}
System.out.println(i);
} catch (IOException e) {
e.printStackTrace();
}
}
}
but my process will not end! I keep getting this error:
java.lang.IllegalThreadStateException: process has not exited
Any ideas as to why my process will not exit? Or do you have any libraries to suggest that handle executing batch files properly and wait until the execution is finished?
Start cmd with the /c switch instead of /k and get rid of the start:
Process p = Runtime.getRuntime().exec(
"cmd /c SQLScriptsToRun.bat" + " -UuserName -Ppassword"
+ " projectName");
/k tells cmd: “Run that command and then stay open”, while /c says “Run that command and then exit.”
/k is for interactive use where you want an initializing batch file and afterwards still use the console.
Your main problem here, however, is that you are creating yet another process by using start. To run a batch file this is totally unnecessary and prevents you from knowing when the batch was run completely, since Java has a reference to the original cmd process you started, not the one you spawned with start.
In principle, this now looks like the following:
Java program starts
Java program runs cmd and instructs it to run start foo.bat and stay open for interactive input (/k)
Java memorizes the process ID (PID 42) to later reference that process
cmd (PID 42) starts
cmd (PID 42) runs start foo.bat
start foo.bat launches another instance of cmd, since that's what should happen to run batch files
cmd (PID 57005) starts
cmd (PID 57005) runs foo.bat
cmd (PID 57005) exits (This marks the event you'd like to know about)
cmd (PID 42) shows the prompt and obediently waits for input (unbeknownst to them the prompt is never seen by a user and no input will ever come ... but cmd (PID 42) waits ...)
Java likes to know whether the process is finished and checks PID 42
Yup, it's still there. Now what?
What you want (and what above change will do) is:
Java program starts
Java program runs cmd and instructs it to run foo.bat and close after running the command (/c)
Java memorizes the process ID (PID 42) to later reference that process
cmd (PID 42) starts
cmd (PID 42) runs foo.bat
cmd (PID 42) exits
Java likes to know whether the process is finished and checks PID 42
Hooray, the process is gone, the batch file has been run.