3

What I am trying to do it is a program to know if a process it is active on Windows to work with it in Java. I looked on the Internet and found two different solutions:

But it is not at all what I am looking for.

According to the option 1, I would like a method to make reference to the process (and detect if it is active/running) but without searching in the full tasklist and then searching on it. I am searching if there is a direct method to do that.

I also though to add a filter to the tasklist but could not find any filter to only get the process I am looking for. I saw all the options using tasklist /? on my command line.

Then I searched information about the second option and wmic (that I never heard before) and it seems that wmic allows you to execute tasks on the command line (correct me if I am wrong please).

So, here I have two questions:

  • Is there a direct method to know if a process is active on Windows with Java? Trying to avoid searching in the full tasklist or using wmic.

  • If it is impossible, what of the two options that I put above would be better if we talk about efficient programming?

Thanks in advance!

Community
  • 1
  • 1
Francisco Romero
  • 12,787
  • 22
  • 92
  • 167

3 Answers3

9

There is no direct way to query general processes as each OS handles them differently.
You kinda stuck with using proxies such as direct OS commands...

You can however, find a specific process using tasklist.exe with /fi parameter.
e.g: tasklist.exe /nh /fi "Imagename eq chrome.exe"
Note the mandatory double quotes.
Syntax & usage are available on MS Technet site.

Same example, filtering for "chrome.exe" in Java:

String findProcess = "chrome.exe";
String filenameFilter = "/nh /fi \"Imagename eq "+findProcess+"\"";
String tasksCmd = System.getenv("windir") +"/system32/tasklist.exe "+filenameFilter;

Process p = Runtime.getRuntime().exec(tasksCmd);
BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));

ArrayList<String> procs = new ArrayList<String>();
String line = null;
while ((line = input.readLine()) != null) 
    procs.add(line);

input.close();

Boolean processFound = procs.stream().filter(row -> row.indexOf(findProcess) > -1).count() > 0;
// Head-up! If no processes were found - we still get: 
// "INFO: No tasks are running which match the specified criteria."
Leet-Falcon
  • 2,107
  • 2
  • 15
  • 23
  • Thanks for answer. I am going to try your code now but I have some questions. Do you use the `ArrayList` because the `BufferedReader` also returns the PID, name of console, etc...? And also, when you do `Runtime.getRuntime().exec(tasksCmd);` if you already has the process running. Is it creates a new one? Thank you again! – Francisco Romero Feb 01 '16 at 23:08
  • OK with your code I could finally get it but I have one more question. What it's the purpose for the last line of your code?: `Boolean processFound = procs...` If I ommit it the code works but if I put it my code gives to me an Exception so I think it is unnecesary. Is it? – Francisco Romero Feb 02 '16 at 11:56
  • It's Java8 only. You can replace with a standard for loop which looks for the required text. – Leet-Falcon Feb 02 '16 at 13:43
  • The purpose of the last line is to check we didn't get "INFO: No tasks are running which match the specified criteria.". (In this case the array has some content but it's not the required process). – Leet-Falcon Feb 02 '16 at 13:51
  • Is it the same as put a throws Exception? – Francisco Romero Feb 02 '16 at 22:50
  • @Error404 - Join http://chat.stackoverflow.com/rooms/102426/how-to-check-if-a-process-is-running-on-windows so we can check the issue you're facing. – Leet-Falcon Feb 03 '16 at 05:34
2

With Java 9 you can do it like this:

Optional<ProcessHandle> processHandle = ProcessHandle.of(pid);
boolean isrunning = processHandle.isPresent() && processHandle.get().isAlive();

You are now also able, to get some info about the process directly with java.

Optional<ProcessHandle> processHandle = ProcessHandle.of(pid);
if(processHandle.isPresent()) {
 ProcessHandle.Info processInfo = processHandle.get().info();
 System.out.println("COMMAND: " + processInfo.command().orElse(""));
 System.out.println("CLI: " + processInfo.commandLine().orElse(""));
 System.out.println("USER: " + processInfo.user().orElse(""));
 System.out.println("START TIME: " + processInfo.startInstant().orElse(null));
 System.out.println("TOTAL CPU: " + processInfo.totalCpuDuration().orElse(null));

}
pan
  • 1,899
  • 1
  • 16
  • 24
  • 1
    where do you get the pid? If you have the pid you already know that the process is running. – tomsv Nov 21 '18 at 08:47
  • What is the difference between "isPresent()" and "get().isAlive()". Imo "isPresent()" is enough because it also returns false when the process is not alive. Any toughts? – Nur1 Jan 13 '21 at 20:31
0

The best way would be launching the process from the java instance. The advantages of this approach are that you can be fully sure that the process that is running, is the process you started. With tasklist, it is possible for normal users to start a process with the name as the target, or reuse the pid if the program closes.

For information how to start a process, see this question.

Process myProcess = Runtime.getRuntime().exec(command);

You can then use the methods of Process to monitor the state of the program, for example myProcess.exitValue() blocks until the program is closed.

Community
  • 1
  • 1
Ferrybig
  • 18,194
  • 6
  • 57
  • 79
  • Yes it is exactly what I am looking for but trying to do it without execution the process by myself. I know that I have a process active and want to store it on a `Process` variable as you put on your example. Is it a way to do this but without geting all the array of process from the tasklist? – Francisco Romero Feb 01 '16 at 12:27
  • if the process launches another process and closes the other one there is no way of determining if it is alive. this method is flawed. – nullsector76 Jul 20 '21 at 06:54