如何使用Java获取当前打开的窗口/进程的列表?


94

有谁知道如何使用Java获取当前打开的窗口或本地计算机的进程?

我想要做的是:像Windows Taskmanager一样列出当前打开的任务,窗口或打开的进程,但使用多平台方法-如果可能,仅使用Java。

Answers:


104

这是从命令“ 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();
}

如果使用的是Windows,则应更改以下行:“ Process p = Runtime.getRun ...”等(第三行),如下所示:

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

希望该信息对您有所帮助!


如何获得流程的开始时间和结束时间
雄鹿队2012年

34
在Windows上,运行tasklist.exe /fo csv /nh以获取CSV格式的列表,这很容易解析。
伊曼纽尔·布尔格

但它没有显示jar名称。我的可执行jar名称是helloDemo.jar。但是它并没有显示任何东西
Sumon Bappi

如果添加|为什么不起作用?grep java的?即ps -elf | grep java不会返回任何东西,但ps -elf会按预期工作。
Itay Moav -Malimovka's

应该注意的是,底部的“特定于Windows”位似乎不必要。在Windows 10上(.exec (Runtime/getRuntime) "tasklist"))(在Clojure中,使用Java-interop)tasklist即使没有指定目录也可以正确返回该过程。
Carcigenicate's

39

最后,对于Java 9+,可以使用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("-");
}

输出:

    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

应该添加哪些导入才能与ProcessHandle一起使用?
Jordi

2
这个类是java.lang如此没有进口需要
雨果M.

23

在Windows上,还有使用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);
    }
}

这仅给命令名称,而不是整个命令行。有没有办法获得整个命令行?
克里斯托弗·丹西

2
您可以致电以获得完整路径GetModuleFileName。有关示例,请参见stackoverflow.com/questions/7521693/…
伊曼纽尔·布尔格

唯一的问题是,它仅给出进程的路径,而不是整个命令行。有没有办法获取进程的完整命令行(即“ ant.bat -f helloWorld.ext”)?
克里斯托弗·丹西

如何检查xyz.exe之类的特定进程是否正在运行?
unknownbits 2013年

@ChristopherDancy不知道您是否仍然需要答案,但是要确保完整性,而且这里也没有提到:Winodws管理信息命令行(或简称wmic.exe)提供了一种检索大量正在运行的应用程序信息的方法- WMIC PROCESS或限制特定过程的输出:WMIC PROCESS WHERE name='theName'。如果需要,可以使用其他过滤器来限制输出。命令行包含在返回表的CommandLine列中(=第二列)
Roman Vottner 2014年

9

我能想到的唯一方法是调用一个为您完成任务的命令行应用程序,然后对输出进行屏幕抓取(例如Linux的ps和Window的任务列表)。

不幸的是,这意味着您将必须编写一些解析例程以从两者中读取数据。

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

1
是的,我也已经考虑过了,但是我坚决只能用Java做到这一点。而且我认为我最好使用“ ps -aux”而不是top。感谢您及时回复!
ramayac

在Windows上,tasklist可以将程序配置为输出CSV :)
MauganRa

7

YAJSW(还有另一个Java服务包装程序)看起来像它的org.rzo.yajsw.os.TaskList接口的基于JNA的实现,适用于win32,linux,bsd和solaris,并且已获得LGPL许可。我没有尝试直接调用此代码,但是当我过去使用YAJSW时,它的效果非常好,因此您不必担心太多。


显然v12 +是Apache / LGPL双重许可
harschware 2015年

5

您可以使用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("------------------");
}

这个库似乎很慢...是否有这个原因(或者是跨vbs的通用java + wmi互操作?
Gobliins

2
我猜您在谈论Windows实现。是的,通常WMI查询需要一些时间。与往常一样,这取决于用例。如果您需要每10毫秒执行一次查询,是的,它太慢了。
profesor_falken

是的,我说的是胜利,在Linux中我发现使用“ ps ... <options>”,因此我认为它应该快得多
Gobliins

好的,如果您愿意,可以在github项目中创建一个问题,我最终将看一下是否可以提高Win的性能。实际上,我在Linux上使用了它,因此我没有过多注意赢得实现:-S
profesor_falken

很好,但是我一直在寻找:在您的流程startTime中,如果我没有记错,您将给定时间限制为一天(hh:mm:ss)。是否可以选择日期和时间(yyyy-mm-dd-hh:mm:ss)?
Gobliins '16

4

没有与平台无关的方法。在Java的1.6版本中,添加了“ Desktop ”类,该类允许以可移植的方式浏览,编辑,邮寄,打开和打印URI。可能有一天有可能将此课程扩展到支持流程,但我对此表示怀疑。

如果您只是对Java进程感到好奇,则可以使用java.lang.management api获取JVM上的线程/内存信息。


4

对于Windows,我使用以下命令:

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");

4

这对于具有捆绑JRE的应用程序可能有用:我扫描从以下位置运行应用程序的文件夹名称:因此,如果您正在从以下位置运行应用程序:

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

那么您可以通过以下方式找到它是否已经在J9中运行:

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");
}

3

最好使用代码ps aux为Linux和tasklistWindows 进行解析,直到出现更通用的东西为止。

对于Windows,您可以参考:http : //www.rgagnon.com/javadetails/java-0593.html

Linux也可以ps aux通过管道传递结果grep,这将使处理/搜索变得快速而容易。我相信您也可以在Windows上找到类似的东西。


您可能还想更详细地查看任务列表:technet.microsoft.com/zh-cn/library/bb491010.aspx
James Oravec 2012年

2

以下程序仅与Java 9+版本兼容...

要获取CurrentProcess信息,

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);
    }
}

对于所有正在运行的进程,

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());
        });
    }
}

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();

我们必须使用process.getOutputStream.close()它,否则它将被锁定在while循环中。


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 

任务列表/ v / FI“状态eq正在运行” / FO“ CSV” / FI“用户名eq LHPL002 \ soft” / FI“ MEMUSAGE gt 10000” / FI“ Windowtitle ne N / A” / NH


0

这是我的函数代码,该函数获取任务并获取其名称,还将它们添加到列表中以从列表中进行访问。它使用数据创建临时文件,读取文件并获得带有.exe后缀的任务名称,并在程序以System.exit(0)退出时安排要删除的文件,并且还隐藏了用于获取任务以及java.exe,以便用户不会意外终止一起运行该程序的进程。

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();
}

我还将这段代码制作成完整的程序,以尝试复制Windows 10的内置任务管理器,如果有兴趣的人,我可以向您发送演示。
Dylan Wedman '18
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.