112

Does any one know how do I get the current open windows or process of a local machine using Java?

What I'm trying to do is: list the current open task, windows or process open, like in Windows Taskmanager, but using a multi-platform approach - using only Java if it's possible.

14 Answers 14

114

This is another approach to parse the the process list from the command "ps -e":

try {
    String line;
    Process p = Runtime.getRuntime().exec("ps -e");
    BufferedReader input =
            new BufferedReader(new InputStreamReader(p.getInputStream()));
    while ((line = input.readLine()) != null) {
        System.out.println(line); //<-- Parse data here.
    }
    input.close();
} catch (Exception err) {
    err.printStackTrace();
}

If you are using Windows, then you should change the line: "Process p = Runtime.getRun..." etc... (3rd line), for one that looks like this:

Process p = Runtime.getRuntime().exec
    (System.getenv("windir") +"\\system32\\"+"tasklist.exe");

Hope the info helps!

Sign up to request clarification or add additional context in comments.

6 Comments

how to get the process start time and end time
On Windows, run tasklist.exe /fo csv /nh to get the list in CSV format, that's much easier to parse.
but it is not showing the jar name. My executable jar name is helloDemo.jar. but it is not showing anything for it
Why wouldn't it work if I add a | grep java ? i.e. ps -elf | grep java won't return a thing, but ps -elf would work as expected.
For anyone on Java 18, this exec command has been deprecated, but you just need to simply change it to an array. Process p = Runtime.getRuntime().exec(new String[] {(System.getenv("windir") +"\\system32\\"+"tasklist.exe"} );
|
65

Finally, with Java 9+ it is possible with ProcessHandle:

public static void main(String[] args) {
    ProcessHandle.allProcesses()
            .forEach(process -> System.out.println(processDetails(process)));
}

private static String processDetails(ProcessHandle process) {
    return String.format("%8d %8s %10s %26s %-40s",
            process.pid(),
            text(process.parent().map(ProcessHandle::pid)),
            text(process.info().user()),
            text(process.info().startInstant()),
            text(process.info().commandLine()));
}

private static String text(Optional<?> optional) {
    return optional.map(Object::toString).orElse("-");
}

Output:

    1        -       root   2017-11-19T18:01:13.100Z /sbin/init
  ...
  639     1325   www-data   2018-12-04T06:35:58.680Z /usr/sbin/apache2 -k start
  ...
23082    11054    huguesm   2018-12-04T10:24:22.100Z /.../java ProcessListDemo

5 Comments

Which imports should be added to work with ProcessHandle?
That class is in java.lang so no import needed
@Jordi: You'd just need import java.util.Optional;. If you use a decent IDE (IntelliJ IDEA/NetBeans/Eclipse/...), necessary imports should be added automatically if you paste the above methods inside an existing class.
Just tried it on Win10 with Java21 (GraalVM) and it worked, except that .commandLine() was always empty. It worked when using .command() instead.
@mazi .command() is the path of the .exe file for that process. commandLine() is the command line used to start that process, e.g. typing notepad thisisatest in command prompt starts a notepad process with that info in the according column in Task Manager. For some reason the latter always seems to be empty when used with Windows (tested with Java 11/Win 10).
26

On Windows there is an alternative using JNA:

import com.sun.jna.Native;
import com.sun.jna.platform.win32.*;
import com.sun.jna.win32.W32APIOptions;

public class ProcessList {

    public static void main(String[] args) {
        WinNT winNT = (WinNT) Native.loadLibrary(WinNT.class, W32APIOptions.UNICODE_OPTIONS);

        WinNT.HANDLE snapshot = winNT.CreateToolhelp32Snapshot(Tlhelp32.TH32CS_SNAPPROCESS, new WinDef.DWORD(0));

        Tlhelp32.PROCESSENTRY32.ByReference processEntry = new Tlhelp32.PROCESSENTRY32.ByReference();

        while (winNT.Process32Next(snapshot, processEntry)) {
            System.out.println(processEntry.th32ProcessID + "\t" + Native.toString(processEntry.szExeFile));
        }

        winNT.CloseHandle(snapshot);
    }
}

7 Comments

This only gives the command name NOT the entire command line. Is there a way to get the entire command line?
You can get the full path by calling GetModuleFileName. See stackoverflow.com/questions/7521693/… for an example.
The only problem w/ this is that it gives only the path of the process NOT the entire command line. Is there a way to get the full command line of the process (i.e. 'ant.bat -f helloWorld.ext')?
how to check for a particular process like xyz.exe is running or not?
@ChristopherDancy oh, forgot to mention: you can even extract the command line directly by using WMIC PROCESS WHERE "name like '%nameOfApp%'" get Commandline
|
10

The only way I can think of doing it is by invoking a command line application that does the job for you and then screenscraping the output (like Linux's ps and Window's tasklist).

Unfortunately, that'll mean you'll have to write some parsing routines to read the data from both.

Process proc = Runtime.getRuntime().exec ("tasklist.exe");
InputStream procOutput = proc.getInputStream ();
if (0 == proc.waitFor ()) {
    // TODO scan the procOutput for your data
}

2 Comments

Yep,I already thought about that too, but I tough it could be done with Java only. And I think I would be better to use "ps -aux" instead of top. Thanks for the quick answer!
On Windows, the tasklist program can be configured to output CSV :)
7

YAJSW (Yet Another Java Service Wrapper) looks like it has JNA-based implementations of its org.rzo.yajsw.os.TaskList interface for win32, linux, bsd and solaris and is under an LGPL license. I haven't tried calling this code directly, but YAJSW works really well when I've used it in the past, so you shouldn't have too many worries.

1 Comment

apparently v12+ is Apache/LGPL dual license
6

You can easily retrieve the list of running processes using jProcesses

List<ProcessInfo> processesList = JProcesses.getProcessList();

for (final ProcessInfo processInfo : processesList) {
    System.out.println("Process PID: " + processInfo.getPid());
    System.out.println("Process Name: " + processInfo.getName());
    System.out.println("Process Used Time: " + processInfo.getTime());
    System.out.println("Full command: " + processInfo.getCommand());
    System.out.println("------------------");
}

7 Comments

this library seems to be very slow... is there a reason for this (or is it general java + wmi interop across vbs?
I guess you talk about windows implementation. Yes, normally WMI queries take some time. As always it depends on the use case. If you need to perform the query every 10 ms, yes, it is too slow.
yes i was talking about win, in linux i spotted the use of "ps...<options>" so i guess it should be much faster
Ok, if you want you can create an issue in the github project and I will eventually take a look and see if I can improve performance in Win. In fact I used it on Linux so I did not pay much attention to win implementation :-S
It is fine, but what i was looking for: In your process startTime you have limited the given time for one day (hh:mm:ss) if i am not wrong. Is there any option to get also the date + time ( yyyy-mm-dd-hh:mm:ss) ?
|
4

There is no platform-neutral way of doing this. In the 1.6 release of Java, a "Desktop" class was added the allows portable ways of browsing, editing, mailing, opening, and printing URI's. It is possible this class may someday be extended to support processes, but I doubt it.

If you are only curious in Java processes, you can use the java.lang.management api for getting thread/memory information on the JVM.

Comments

4

For windows I use following:

Process process = new ProcessBuilder("tasklist.exe", "/fo", "csv", "/nh").start();
new Thread(() -> {
    Scanner sc = new Scanner(process.getInputStream());
    if (sc.hasNextLine()) sc.nextLine();
    while (sc.hasNextLine()) {
        String line = sc.nextLine();
        String[] parts = line.split(",");
        String unq = parts[0].substring(1).replaceFirst(".$", "");
        String pid = parts[1].substring(1).replaceFirst(".$", "");
        System.out.println(unq + " " + pid);
    }
}).start();
process.waitFor();
System.out.println("Done");

Comments

4

This might be useful for apps with a bundled JRE: I scan for the folder name that i'm running the application from: so if you're application is executing from:

C:\Dev\build\SomeJavaApp\jre-9.0.1\bin\javaw.exe

then you can find if it's already running in J9, by:

public static void main(String[] args) {
    AtomicBoolean isRunning = new AtomicBoolean(false);
    ProcessHandle.allProcesses()
            .filter(ph -> ph.info().command().isPresent() && ph.info().command().get().contains("SomeJavaApp"))
            .forEach((process) -> {
                isRunning.set(true);
            });
    if (isRunning.get()) System.out.println("SomeJavaApp is running already");
}

Comments

3

Using code to parse ps aux for linux and tasklist for windows are your best options, until something more general comes along.

For windows, you can reference: http://www.rgagnon.com/javadetails/java-0593.html

Linux can pipe the results of ps aux through grep too, which would make processing/searching quick and easy. I'm sure you can find something similar for windows too.

1 Comment

You may want to look at tasklist in more detail too: technet.microsoft.com/en-us/library/bb491010.aspx
2

The below program will be compatible with Java 9+ version only...

To get the CurrentProcess information,

public class CurrentProcess {
    public static void main(String[] args) {
        ProcessHandle handle = ProcessHandle.current();
        System.out.println("Current Running Process Id: "+handle.pid());
        ProcessHandle.Info info = handle.info();
        System.out.println("ProcessHandle.Info : "+info);
    }
}

For all running processes,

import java.util.List;
import java.util.stream.Collectors;

public class AllProcesses {
    public static void main(String[] args) {
        ProcessHandle.allProcesses().forEach(processHandle -> {
            System.out.println(processHandle.pid()+" "+processHandle.info());
        });
    }
}

Comments

2

    String line;
    Process process = Runtime.getRuntime().exec("ps -e");
    process.getOutputStream().close();
    BufferedReader input =
            new BufferedReader(new InputStreamReader(process.getInputStream()));
    while ((line = input.readLine()) != null) {
        System.out.println(line); //<-- Parse data here.
    }
    input.close();

We have to use process.getOutputStream.close() otherwise it will get locked in while loop.

Comments

0
package com.vipul;

import java.applet.Applet;
import java.awt.Checkbox;
import java.awt.Choice;
import java.awt.Font;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

public class BatchExecuteService extends Applet {
    public Choice choice;

    public void init() 
    {
        setFont(new Font("Helvetica", Font.BOLD, 36));
        choice = new Choice();
    }

    public static void main(String[] args) {
        BatchExecuteService batchExecuteService = new BatchExecuteService();
        batchExecuteService.run();
    }

    List<String> processList = new ArrayList<String>();

    public void run() {
        try {
            Runtime runtime = Runtime.getRuntime();
            Process process = runtime.exec("D:\\server.bat");
            process.getOutputStream().close();
            InputStream inputStream = process.getInputStream();
            InputStreamReader inputstreamreader = new InputStreamReader(
                    inputStream);
            BufferedReader bufferedrReader = new BufferedReader(
                    inputstreamreader);
            BufferedReader bufferedrReader1 = new BufferedReader(
                    inputstreamreader);

            String strLine = "";
            String x[]=new String[100];
            int i=0;
            int t=0;
            while ((strLine = bufferedrReader.readLine()) != null) 
            {
        //      System.out.println(strLine);
                String[] a=strLine.split(",");
                x[i++]=a[0];
            }
    //      System.out.println("Length : "+i);

            for(int j=2;j<i;j++)
            {
                System.out.println(x[j]);
            }
        }
        catch (IOException ioException) 
        {
            ioException.printStackTrace();
        }

    }
}
   You can create batch file like 

TASKLIST /v /FI "STATUS eq running" /FO "CSV" /FI "Username eq LHPL002\soft" /FI "MEMUSAGE gt 10000" /FI "Windowtitle ne N/A" /NH

Comments

0

This is my code for a function that gets the tasks and gets their names, also adding them into a list to be accessed from a list. It creates temp files with the data, reads the files and gets the task name with the .exe suffix, and arranges the files to be deleted when the program has exited with System.exit(0), it also hides the processes being used to get the tasks and also java.exe so that the user can't accidentally kill the process that runs the program all together.

private static final DefaultListModel tasks = new DefaultListModel();

public static void getTasks()
{
    new Thread()
    {
        @Override
        public void run()
        {
            try 
            {
                File batchFile = File.createTempFile("batchFile", ".bat");
                File logFile = File.createTempFile("log", ".txt");
                String logFilePath = logFile.getAbsolutePath();
                try (PrintWriter fileCreator = new PrintWriter(batchFile)) 
                {
                    String[] linesToPrint = {"@echo off", "tasklist.exe >>" + logFilePath, "exit"};
                    for(String string:linesToPrint)
                    {
                        fileCreator.println(string);
                    }
                    fileCreator.close();
                }
                int task = Runtime.getRuntime().exec(batchFile.getAbsolutePath()).waitFor();
                if(task == 0)
                {
                    FileReader fileOpener = new FileReader(logFile);
                    try (BufferedReader reader = new BufferedReader(fileOpener))
                    {
                        String line;
                        while(true)
                        {
                            line = reader.readLine();
                            if(line != null)
                            {
                                if(line.endsWith("K"))
                                {
                                    if(line.contains(".exe"))
                                    {
                                        int index = line.lastIndexOf(".exe", line.length());
                                        String taskName = line.substring(0, index + 4);
                                        if(! taskName.equals("tasklist.exe") && ! taskName.equals("cmd.exe") && ! taskName.equals("java.exe"))
                                        {
                                            tasks.addElement(taskName);
                                        }
                                    }
                                }
                            }
                            else
                            {
                                reader.close();
                                break;
                            }
                        }
                    }
                }
                batchFile.deleteOnExit();
                logFile.deleteOnExit();
            } 
            catch (FileNotFoundException ex) 
            {
                Logger.getLogger(Functions.class.getName()).log(Level.SEVERE, null, ex);
            } 
            catch (IOException | InterruptedException ex) 
            {
                Logger.getLogger(Functions.class.getName()).log(Level.SEVERE, null, ex);
            }
            catch (NullPointerException ex)
            {
                // This stops errors from being thrown on an empty line
            }
        }
    }.start();
}

public static void killTask(String taskName)
{
    new Thread()
    {
        @Override
        public void run()
        {
            try 
            {
                Runtime.getRuntime().exec("taskkill.exe /IM " + taskName);
            } 
            catch (IOException ex) 
            {
                Logger.getLogger(Functions.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }.start();
}

1 Comment

I've also made this code into a full program to try and replicate the built-in task manager for Windows 10, if anyone is interested, I can send you a demo of it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.