109

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.

tshepang
  • 12,111
  • 21
  • 91
  • 136
ramayac
  • 5,173
  • 10
  • 50
  • 58

14 Answers14

115

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!

Josh Crozier
  • 233,099
  • 56
  • 391
  • 304
ramayac
  • 5,173
  • 10
  • 50
  • 58
  • how to get the process start time and end time – Bucks Sep 11 '12 at 09:27
  • 36
    On Windows, run `tasklist.exe /fo csv /nh` to get the list in CSV format, that's much easier to parse. – Emmanuel Bourg Jan 24 '13 at 15:31
  • but it is not showing the jar name. My executable jar name is helloDemo.jar. but it is not showing anything for it – Sumon Bappi May 02 '15 at 10:57
  • 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. – Itay Moav -Malimovka May 02 '16 at 20:28
  • It should be noted that the "windows specific" bit at the bottom appears to be unnecessary. On Windows 10, `(.exec (Runtime/getRuntime) "tasklist"))` (in Clojure, using Java-interop) correctly returns the `tasklist` process, even without specifying a directory. – Carcigenicate Jan 09 '17 at 18:25
  • 1
    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"} );` – Austin Whitelaw May 02 '22 at 17:36
59

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
Hugues M.
  • 19,846
  • 6
  • 37
  • 65
  • 1
    Which imports should be added to work with ProcessHandle? – Jordi May 28 '18 at 16:35
  • 2
    That class is in `java.lang` so no import needed – Hugues M. May 28 '18 at 16:42
  • 1
    @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. – Eric Duminil Oct 17 '22 at 08:49
25

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);
    }
}
Emmanuel Bourg
  • 9,601
  • 3
  • 48
  • 76
  • 1
    This only gives the command name NOT the entire command line. Is there a way to get the entire command line? – Christopher Dancy May 04 '13 at 19:31
  • 2
    You can get the full path by calling `GetModuleFileName`. See http://stackoverflow.com/questions/7521693/converting-c-sharp-to-java-jna-getmodulefilename-from-hwnd for an example. – Emmanuel Bourg May 06 '13 at 08:29
  • 1
    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')? – Christopher Dancy May 06 '13 at 16:31
  • how to check for a particular process like xyz.exe is running or not? – unknownbits Jul 05 '13 at 06:31
  • @ChristopherDancy not sure if you still need an answer but for completeness and and as it wasn't mentioned here either: [Winodws Managment Information Command-line (or simply wmic.exe)](http://technet.microsoft.com/en-us/library/bb742610.aspx) provides a way to retrieve plenty of information of running applications - `WMIC PROCESS` or to restrict the output for a specific process: `WMIC PROCESS WHERE name='theName'`. You can use further filters to limit the output if needed. The command line is included in the CommandLine column of the table returned (= 2nd column) – Roman Vottner Jan 13 '14 at 13:51
  • @PrashantSharma You can check `WMIC PROCESS WHERE name='nameOfApp'` if the second line (first line is the table header) contains `No instance available` there is no running process with that name, else you get a bunch of information regarding the running process. – Roman Vottner Jan 13 '14 at 13:55
  • 1
    @ChristopherDancy oh, forgot to mention: you can even extract the command line directly by using `WMIC PROCESS WHERE "name like '%nameOfApp%'" get Commandline` – Roman Vottner Jan 13 '14 at 14:01
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
}
jodonnell
  • 49,859
  • 10
  • 62
  • 67
  • 1
    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! – ramayac Sep 10 '08 at 17:04
  • On Windows, the `tasklist` program can be configured to output CSV :) – MauganRa Mar 10 '17 at 08:41
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.

SamWest
  • 132
  • 1
  • 8
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("------------------");
}
Irwin Nawrocki
  • 337
  • 4
  • 7
profesor_falken
  • 559
  • 6
  • 10
  • this library seems to be very slow... is there a reason for this (or is it general java + wmi interop across vbs? – Gobliins Apr 18 '16 at 12:18
  • 2
    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. – profesor_falken Apr 18 '16 at 12:27
  • yes i was talking about win, in linux i spotted the use of "ps..." so i guess it should be much faster – Gobliins Apr 18 '16 at 12:35
  • 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 – profesor_falken Apr 18 '16 at 12:43
  • 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) ? – Gobliins Apr 18 '16 at 13:49
  • Umm it is not normal. The startTime is taken from CreationDate property of WIN32_PROCESS class (https://msdn.microsoft.com/en-us/library/windows/desktop/aa394372(v=vs.85).aspx), which is normally something like '20160418081141.713311+120'. Please create an issue and I will take it a look. I do no have acces to a windows machine right now. – profesor_falken Apr 18 '16 at 15:12
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");
Miss Chanandler Bong
  • 4,081
  • 10
  • 26
  • 36
Stepan Yakovenko
  • 8,670
  • 28
  • 113
  • 206
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");
}
Miss Chanandler Bong
  • 4,081
  • 10
  • 26
  • 36
wax_lyrical
  • 922
  • 1
  • 10
  • 22
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.

hazzen
  • 17,128
  • 6
  • 41
  • 33
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.

James Oravec
  • 19,579
  • 27
  • 94
  • 160
3

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());
        });
    }
}
Nallamachu
  • 1,420
  • 18
  • 34
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.

Jijo Joy
  • 21
  • 1
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

Panchotiya Vipul
  • 1,226
  • 5
  • 17
  • 42
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();
}
  • 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. – Dylan Wedman Dec 29 '18 at 01:53