Как получить список текущих открытых окон / процессов с помощью Java?

Кто-нибудь знает, как мне получить текущие открытые окна или процесс на локальном компьютере с помощью Java?

Я пытаюсь сделать следующее: перечислить текущую открытую задачу, окна или открытые процессы, как в диспетчере задач Windows, но с использованием многоплатформенного подхода - используя только Java, если это возможно.

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
98
0
180 036
14
Перейти к ответу Данный вопрос помечен как решенный

Ответы 14

Единственный способ, которым я могу это сделать, - это вызвать приложение командной строки, которое выполняет эту работу за вас, а затем выполнить сканирование экрана вывода (например, ps в Linux и список задач Windows).

К сожалению, это будет означать, что вам придется написать несколько процедур синтаксического анализа для чтения данных из обоих.

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

Да, я уже думал об этом, но мне кажется, что это можно сделать только с Java. И я думаю, что лучше было бы использовать «ps -aux» вместо top. Спасибо за быстрый ответ!

Rodrigo Amaya 10.09.2008 21:04

В Windows программу tasklist можно настроить для вывода CSV :)

MauganRa 10.03.2017 11:41
Ответ принят как подходящий

Это еще один подход к синтаксическому анализу списка процессов из команды "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 ...» и т. д. (3-я строка), чтобы она выглядела так:

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

Надеюсь, информация поможет!

как получить время начала и окончания процесса

Bucks 11.09.2012 13:27

В Windows запустите tasklist.exe /fo csv /nh, чтобы получить список в формате CSV, который намного проще анализировать.

Emmanuel Bourg 24.01.2013 19:31

но имя банки не отображается. Имя моего исполняемого файла - helloDemo.jar. но он ничего не показывает

Sumon Bappi 02.05.2015 13:57

Почему бы не сработать, если я добавлю | grep java? то есть ps -elf | grep java ничего не вернет, но ps -elf будет работать должным образом.

Itay Moav -Malimovka 02.05.2016 23:28

Следует отметить, что бит "специфичный для Windows" внизу кажется ненужным. В Windows 10 (.exec (Runtime/getRuntime) "tasklist")) (в Clojure с использованием Java-interop) правильно возвращает процесс tasklist, даже без указания каталога.

Carcigenicate 09.01.2017 21:25

Не существует нейтрального для платформы способа сделать это. В версии Java 1.6 был добавлен класс «Рабочий стол», позволяющий переносить способы просмотра, редактирования, отправки по почте, открытия и печати URI. Возможно, этот класс когда-нибудь будет расширен для поддержки процессов, но я сомневаюсь в этом.

Если вас интересуют только процессы Java, вы можете использовать java.lang.management api для получения информации о потоках / памяти на JVM.

YAJSW (еще один Java Service Wrapper) выглядит так, как будто он имеет основанные на JNA реализации своего интерфейса org.rzo.yajsw.os.TaskList для win32, linux, bsd и solaris и находится под лицензией LGPL. Я не пробовал вызывать этот код напрямую, но YAJSW работает очень хорошо, когда я использовал его в прошлом, так что у вас не должно быть слишком много проблем.

по-видимому, v12 + - это двойная лицензия Apache / LGPL

harschware 25.02.2015 03:18

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

Это дает только имя команды, а НЕ всю командную строку. Есть ли способ получить всю командную строку?

Christopher Dancy 04.05.2013 23:31

Вы можете получить полный путь, позвонив в GetModuleFileName. См. Пример stackoverflow.com/questions/7521693/….

Emmanuel Bourg 06.05.2013 12:29

Единственная проблема с этим заключается в том, что он дает только путь процесса, а НЕ всю командную строку. Есть ли способ получить полную командную строку процесса (например, ant.bat -f helloWorld.ext)?

Christopher Dancy 06.05.2013 20:31

как проверить, запущен ли конкретный процесс, например xyz.exe?

unknownbits 05.07.2013 10:31

@ChristopherDancy не уверен, нужен ли вам ответ, но для полноты и, как здесь не упоминалось: Командная строка информации об управлении Winodws (или просто wmic.exe) предоставляет способ получить много информации о запущенных приложениях - WMIC PROCESS или ограничить вывод для определенного процесса: WMIC PROCESS WHERE name='theName'. При необходимости вы можете использовать дополнительные фильтры, чтобы ограничить вывод. Командная строка включена в столбец CommandLine возвращаемой таблицы (= 2-й столбец)

Roman Vottner 13.01.2014 17:51

@PrashantSharma Вы можете проверить WMIC PROCESS WHERE name='nameOfApp', если вторая строка (первая строка - заголовок таблицы) содержит No instance available, нет запущенного процесса с таким именем, иначе вы получите кучу информации о запущенном процессе.

Roman Vottner 13.01.2014 17:55

@ChristopherDancy о, забыл упомянуть: вы даже можете извлечь командную строку напрямую, используя WMIC PROCESS WHERE "name like '%nameOfApp%'" get Commandline

Roman Vottner 13.01.2014 18:01

Использование кода для синтаксического анализа ps aux для Linux и tasklist для Windows - ваши лучшие варианты, пока не появится что-то более общее.

Для windows вы можете ссылаться на: http://www.rgagnon.com/javadetails/java-0593.html

Linux также может передавать результаты ps aux через grep, что упростит и ускорит обработку / поиск. Я уверен, что вы можете найти что-то подобное и для окон.

Вы также можете посмотреть список задач более подробно: technet.microsoft.com/en-us/library/bb491010.aspx

James Oravec 17.05.2012 19:46

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

Вы можете легко получить список запущенных процессов, используя 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("------------------");
}

эта библиотека кажется очень медленной ... есть ли для этого причина (или это общее взаимодействие java + wmi через vbs?

Gobliins 18.04.2016 15:18

Я думаю, вы говорите о реализации Windows. Да, обычно запросы WMI занимают некоторое время. Как всегда, это зависит от варианта использования. Если вам нужно выполнять запрос каждые 10 мс, да, это слишком медленно.

profesor_falken 18.04.2016 15:27

да, я говорил о победе, в Linux я заметил использование "ps ... <options>", так что я думаю, это должно быть намного быстрее

Gobliins 18.04.2016 15:35

Хорошо, если вы хотите, вы можете создать проблему в проекте github, и я в конечном итоге посмотрю и посмотрю, смогу ли я улучшить производительность в Win. На самом деле я использовал его в Linux, поэтому не обращал особого внимания на реализацию win: -S

profesor_falken 18.04.2016 15:43

Это нормально, но то, что я искал: в вашем процессе startTime вы ограничили заданное время на один день (чч: мм: сс), если я не ошибаюсь. Есть ли возможность получить также дату + время (гггг-мм-дд-чч: мм: сс)?

Gobliins 18.04.2016 16:49

Умм, это ненормально. Время начала берется из свойства CreationDate класса WIN32_PROCESS (msdn.microsoft.com/en-us/library/windows/desktop/…), которое обычно выглядит примерно так: 20160418081141.713311 + 120. Пожалуйста, создайте проблему, и я рассмотрю ее. У меня сейчас нет доступа к машине с Windows.

profesor_falken 18.04.2016 18:12

Для окон я использую следующее:

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

Наконец, с 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 28.05.2018 19:35

Этот класс находится в java.lang, поэтому импорт не требуется

Hugues M. 28.05.2018 19:42

Это может быть полезно для приложений со встроенной 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");
}

Это мой код для функции, которая получает задачи и их имена, а также добавляет их в список для доступа из списка. Он создает временные файлы с данными, считывает файлы и получает имя задачи с суффиксом .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 29.12.2018 04:53

Приведенная ниже программа будет совместима только с версией 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());
        });
    }
}

    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.

Другие вопросы по теме