Як отримати список поточних відкритих вікон / процесів за допомогою 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.