Як отримати список поточних відкритих вікон / процесів за допомогою Java?


95

Хтось знає, як отримати поточно відкриті вікна або процес локальної машини за допомогою Java?

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

Відповіді:


105

Це ще один підхід до синтаксичного аналізу списку процесів за допомогою команди " 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");

Сподіваюся, інформація допоможе!


як отримати час початку та закінчення процесу
Бакс

34
У Windows запустіть, tasklist.exe /fo csv /nhщоб отримати список у форматі CSV, це набагато легше проаналізувати.
Еммануель Бург

але в ньому не відображається назва банки. Моє ім'я виконуваної банки - helloDemo.jar. але це нічого не показує
Сумон Баппі,

Чому б це не працювало, якщо я додаю | grep java? тобто ps -elf | grep javaне поверне річ, але ps -elfбуде працювати, як очікувалося.
Itay Moav -Malimovka

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

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не потребує імпорту
Хьюг М.,

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

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

9

Єдиний спосіб, як я можу подумати, це зробити, викликаючи програму командного рядка, яка виконує цю роботу за вас, а потім екранізуючи результати (наприклад, ps і список завдань Windows).

На жаль, це означатиме, що вам доведеться написати кілька процедур аналізу, щоб прочитати дані з обох.

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 Service Wrapper), схоже, має реалізації свого інтерфейсу org.rzo.yajsw.os.T.TaskList на основі JNA для win32, linux, bsd та solaris і перебуває під ліцензією LGPL. Я не намагався викликати цей код безпосередньо, але YAJSW працює дуже добре, коли я використовував його раніше, тому у вас не повинно бути занадто багато турбот.


мабуть, v12 + - це подвійна ліцензія Apache / LGPL
програмне забезпечення

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

ця бібліотека здається дуже повільною ... чи є для цього причина (або це загальна взаємодія Java + wmi через vbs?
Gobliins

2
Думаю, ви говорите про впровадження Windows. Так, зазвичай запити WMI займають деякий час. Як завжди, це залежить від випадку використання. Якщо вам потрібно виконати запит кожні 10 мс, так, це занадто повільно.
profesor_falken

так, я говорив про виграш, у Linux я помітив використання "ps ... <варіанти>", тому, мабуть, це має бути набагато швидше
Gobliins

Добре, якщо ви хочете, ви можете створити проблему в проекті github, і я врешті-решт подивлюсь і подивлюсь, чи можу я покращити продуктивність у Win. Насправді я використовував його на Linux, тому не звертав особливої ​​уваги на те, щоб виграти реалізацію: -S
profesor_falken

Це нормально, але те, що я шукав: під час запуску вашого процесу ви обмежили заданий час на одну добу (год-год: мм: сс), якщо я не помиляюся. Чи є можливість отримати також дату + час (рррр-мм-дд-год: мм: сс)?
Gobliins

4

Не існує нейтрального для платформи способу зробити це. У версії Java 1.6, клас " Робочий стіл " був доданий, що дозволяє переносити способи перегляду, редагування, розсилки, відкриття та друку URI. Можливо, цей клас колись може бути розширений для підтримки процесів, але я сумніваюся в цьому.

Якщо вам цікаво лише в процесах Java, ви можете використовувати api java.lang.management для отримання інформації про потоки / пам'ять на JVM.


4

Для вікон я використовую наступне:

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 - найкращі варіанти, поки не з’явиться щось більш загальне.

Щодо вікон, ви можете посилатися на: http://www.rgagnon.com/javadetails/java-0593.html

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


Можливо, ви також захочете переглянути детальніше список завдань: technet.microsoft.com/en-us/library/bb491010.aspx
Джеймс Оравець,

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 "СТАТУС еквалайзера працює" / FO "CSV" / FI "Ім'я користувача eq LHPL002 \ soft" / FI "MEMUSAGE gt 10000" / FI "Заголовок вікна не застосовується" / 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, якщо комусь цікаво, я можу надіслати вам його демонстрацію.
Ділан Ведман,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.