I'm starting a Java process in my Java code. I have coded a function to close this process. But the process doesn't get terminated.
Here is my code for create the process:
Process process = null;
final ProcessBuilder builder = new ProcessBuilder("java", "-jar", "-Xmx512M", "server.jar");
builder.directory(new File("temp/"+serverName+"/"));
try {
process = builder.start();
} catch (IOException e) {
e.printStackTrace();
}
Launcher.serverProcess.put(serverName, process);
from another class I would like to stop the server:
Process temp = Launcher.serverProcess.get(serverName);
while(temp.isAlive()) {
temp.destroy();
temp.destroyForcibly();
}
Launcher.serverProcess.remove(serverName);
After entering the command to stop the process, I want to remove the directory. Whenever I try this I am only told that the folder is being used and I cannot delete it. With taskkill / F / IM java.exe I stop the process and can then delete the folder
Related
I am having trouble writing to a command prompt that I can open via ProcessBuilder.
I have the following:
public class Terminal {
public static void main(String[] args) {
List<String> launch = new ArrayList<String>();
launch.add("cmd");
launch.add("/c");
launch.add("start");
launch.add("cmd.exe");
launch.add("/k");
try {
ProcessBuilder builder = new ProcessBuilder(launch);
Process process = builder.start();
OutputStream stdin = process.getOutputStream();
InputStream stdout = process.getInputStream();
BufferedReader r = new BufferedReader(new InputStreamReader(stdout));
BufferedWriter w = new BufferedWriter(new OutputStreamWriter(stdin));
w.write("dir");
w.flush();
w.close();
}
catch (IOException io) {
io.printStackTrace();
}
}
}
And this successfully opens a new Windows command prompt. But it never writes dir to it. The prompt just opens and only displays the directory from which java Terminal was issued.
How can I actively write to a terminal opened via a Process?
Edit:
If I change the command string list to "cmd.exe /k start dir" then the newly spawned command prompt does in fact issue the "dir" command and display it in the new terminal. I cannot seem to find the correct manner to access the stream for writing new commands to it.
public class Terminal {
public static void main(String[] args) {
List<String> launch = new ArrayList<String>();
launch.add("cmd");
launch.add("/k");
launch.add("start");
launch.add("dir");
try {
Process p = new ProcessBuilder(launch).start();
}
catch (IOException io) {
io.printStackTrace();
}
}
}
Lets take a look at what cmd /c start cmd /k does:
cmd /c starts a command prompt, executes the following commands, then exits.
start spawns a new process with the given commands
cmd /k expects a command (which you dont provide), executes it, then remains open
So: You start two instances of cmd. The second instance is started using start, which spawns a new process. You expect "dir" to show up in the second process, while it is being written to the first. Unfortunately, the first terminates immediately after calling start since you started it with /c.
Try changing /c to /k, then the "dir" should show up in the first window.
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.
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
I've set this OnClick method in JavaFX SceneBuilder on a text field that will pop up the Windows 8 touch keyboard if the user select the textfield. However it seems to be nothing happen when I click on the textfield but when I try to check Tabtip.exe in the task manager, it did shown up there. The codes are:
try
{
Runtime rt = Runtime.getRtuntime();
rt.exec( "cmd /c C:\\Programs Files\\Common Files\\Microsoft Shared\\ink\\TabTip.exe");
}
catch
{
ex.printStackTrace();
}
There is not errors triggered or whatsoever, and TabTip.exe is running in task manager, but the pop up keyboard does not show up, anyone has any solution to this? Thanks!
Whenever you want to execute a command which contains spaces in command prompt, you have to wrap it in double quotes.
Like this:
String commandStr = "cmd /c \"C:\\Program Files\\Common Files\\Microsoft Shared\\ink\\mip.exe\"";
rt.exec( commandStr );
And In addition to that, if you want to know your errors, you can get error stream from object of class Process which is returned by runtimeObject.exec().
String commandStr = "cmd /c C:\\Programs Files\\Common Files\\Microsoft Shared\\ink\\TabTip.exe"; // Like you did
InputStream is = rt.exec( commandStr ).getErrorStream();
int b;
while((b=(is.read()))!=-1)
System.out.print((char)b);
}
Please do like this. For me it is ok in window10 with javaFx application.
ProcessBuilder builder = new ProcessBuilder("cmd.exe", "/c", "\"C:\\Program Files\\Common Files\\microsoft shared\\ink\\TabTip.exe");
builder.redirectErrorStream(true);
Process p;
try
{
p = builder.start();
BufferedReader r = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line;
while (true)
{
line = r.readLine();
if (line == null)
{
break;
}
System.out.println(line);
}
}
catch (IOException e)`enter code here`
{
// TODO Auto-generated catch block
e.printStackTrace();
}`enter code here`
The only way to run the TabTip.exe is to run the software on Admin mode.
I found the following batch code on the internet.
How to Use On-Screen and Touch Keyboard Instead of Spiral Keyboard
tasklist | find /I "TabTip.exe" >NUL && (taskkill /IM "TabTip.exe" /T)
start "" "TabTip.exe"
That code kills the TabTip process and executes a new TabTip.
In my case, I created a file called keyboard.bat and added the previous example.
In java, I created a method in order to read this file in the same folder.
That is my code
try{
File file = new File("keyboard.bat");
Runtime.getRuntime().exec(file.getAbsolutePath());
}catch(IOException ex){
Logger.getLogger(RunGazePoint.class.getName()).log(Level.SEVERE, null, ex);
}
after that, I compile my app and wrap it in executable mode with launch4j software.
Another way Is to execute by command, If you are using a multithreaded the system can avoid the lecture of file and not execute the software.
create two methods in order to kill and call the keyboard.
//hide the Keyboard
String[] array = new String[]{"cmd.exe","/c","taskkill /IM \"TabTip.exe\" /F\n" +
""};
Runtime.getRuntime().exec(array);
//Show the keyboard
String[] array = new String[]{"cmd.exe","/c","start \"\" \"TabTip.exe\""};
Runtime.getRuntime().exec(array);
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.