Comment obtenir une liste des fenêtres / processus ouverts actuels avec Java?


95

Est-ce que quelqu'un sait comment obtenir les fenêtres ou processus ouverts actuels d'une machine locale en utilisant Java?

Ce que j'essaie de faire est de: lister la tâche ouverte actuelle, les fenêtres ou le processus ouverts, comme dans Windows Taskmanager, mais en utilisant une approche multi-plateforme - en utilisant uniquement Java si c'est possible.

Réponses:


105

Ceci est une autre approche pour analyser la liste des processus à partir de la commande " 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();
}

Si vous utilisez Windows, vous devez changer la ligne: "Process p = Runtime.getRun ..." etc ... (3ème ligne), pour celle qui ressemble à ceci:

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

J'espère que les informations vous aideront!


comment obtenir l'heure de début et de fin du processus
Bucks

34
Sous Windows, exécutez tasklist.exe /fo csv /nhpour obtenir la liste au format CSV, c'est beaucoup plus facile à analyser.
Emmanuel Bourg

mais il ne montre pas le nom du pot. Le nom de mon fichier exécutable est helloDemo.jar. mais il ne montre rien pour cela
Sumon Bappi

Pourquoi cela ne fonctionnerait-il pas si j'ajoute un | grep java? ie ps -elf | grep javane retournera rien, mais ps -elffonctionnerait comme prévu.
Itay Moav -Malimovka

Il convient de noter que le bit "spécifique à Windows" en bas semble inutile. Sous Windows 10, (.exec (Runtime/getRuntime) "tasklist"))(dans Clojure, à l'aide de Java-interop) renvoie correctement le tasklistprocessus, même sans spécifier de répertoire.
Carcigenicate

39

Enfin, avec Java 9+, il est possible avec 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("-");
}

Production:

    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

Quelles importations doivent être ajoutées pour fonctionner avec ProcessHandle?
Jordi

2
Cette classe est java.langdonc aucune importation nécessaire
Hugues M.

23

Sous Windows, il existe une alternative utilisant 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);
    }
}

Cela ne donne que le nom de la commande PAS la ligne de commande entière. Existe-t-il un moyen d'obtenir la ligne de commande entière?
Christopher Dancy

2
Vous pouvez obtenir le chemin complet en appelant GetModuleFileName. Voir stackoverflow.com/questions/7521693/… pour un exemple.
Emmanuel Bourg

Le seul problème avec ceci est qu'il ne donne que le chemin du processus PAS la ligne de commande entière. Existe-t-il un moyen d'obtenir la ligne de commande complète du processus (c'est-à-dire «ant.bat -f helloWorld.ext»)?
Christopher Dancy

comment vérifier un processus particulier comme xyz.exe est en cours d'exécution ou non?
unknownbits

@ChristopherDancy ne sait pas si vous avez encore besoin d'une réponse, mais par souci d'exhaustivité et comme cela n'a pas été mentionné ici non plus: La ligne de commande Winodws Managment Information (ou simplement wmic.exe) fournit un moyen de récupérer de nombreuses informations sur les applications en cours d'exécution - WMIC PROCESSou pour limiter la sortie d'un processus spécifique: WMIC PROCESS WHERE name='theName'. Vous pouvez utiliser d'autres filtres pour limiter la sortie si nécessaire. La ligne de commande est incluse dans la colonne CommandLine du tableau renvoyé (= 2e colonne)
Roman Vottner

9

La seule façon dont je peux penser à le faire est d'appeler une application de ligne de commande qui fait le travail pour vous, puis de capturer la sortie (comme ps de Linux et la liste des tâches de Windows).

Malheureusement, cela signifie que vous devrez écrire des routines d'analyse pour lire les données des deux.

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

1
Oui, j'ai déjà pensé à cela aussi, mais je pense que cela pourrait être fait uniquement avec Java. Et je pense que je ferais mieux d'utiliser "ps -aux" au lieu de top. Merci pour la réponse rapide!
ramayac

Sous Windows, le tasklistprogramme peut être configuré pour sortir CSV :)
MauganRa

7

YAJSW (Yet Another Java Service Wrapper) semble avoir des implémentations basées sur JNA de son interface org.rzo.yajsw.os.TaskList pour win32, linux, bsd et solaris et est sous une licence LGPL. Je n'ai pas essayé d'appeler ce code directement, mais YAJSW fonctionne très bien lorsque je l'ai utilisé dans le passé, vous ne devriez donc pas avoir trop de soucis.


apparemment v12 + est une double licence Apache / LGPL
harschware

5

Vous pouvez facilement récupérer la liste des processus en cours à l'aide de 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("------------------");
}

cette bibliothèque semble être très lente ... y a-t-il une raison à cela (ou est-ce une interopérabilité générale java + wmi entre vbs?
Gobliins

2
Je suppose que vous parlez de la mise en œuvre de Windows. Oui, les requêtes WMI prennent normalement un certain temps. Comme toujours, cela dépend du cas d'utilisation. Si vous devez effectuer la requête toutes les 10 ms, oui, c'est trop lent.
profesor_falken

oui je parlais de win, sous linux j'ai repéré l'utilisation de "ps ... <options>" donc je suppose que ça devrait être beaucoup plus rapide
Gobliins

Ok, si vous le souhaitez, vous pouvez créer un problème dans le projet github et je vais éventuellement jeter un coup d'œil et voir si je peux améliorer les performances dans Win. En fait je l'ai utilisé sous Linux donc je n'ai pas prêté beaucoup d'attention à l'implémentation win: -S
profesor_falken

C'est bien, mais ce que je cherchais: Dans votre processus startTime, vous avez limité le temps donné pour un jour (hh: mm: ss) si je ne me trompe pas. Existe-t-il une option pour obtenir également la date + l'heure (aaaa-mm-jj-hh: mm: ss)?
Gobliins

4

Il n'y a pas de moyen neutre de faire cela. Dans la version 1.6 de Java, une classe " Desktop " a été ajoutée pour permettre des moyens portables de parcourir, modifier, envoyer, ouvrir et imprimer les URI. Il est possible que cette classe soit un jour étendue pour supporter des processus, mais j'en doute.

Si vous n'êtes curieux que des processus Java, vous pouvez utiliser l' API java.lang.management pour obtenir des informations sur les threads / mémoire sur la JVM.


4

Pour Windows, j'utilise ce qui suit:

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

Cela peut être utile pour les applications avec un JRE fourni: je scanne le nom du dossier à partir duquel j'exécute l'application: donc si votre application est en cours d'exécution à partir de:

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

alors vous pouvez trouver s'il fonctionne déjà dans J9, en:

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

Utiliser du code pour analyser ps auxLinux et tasklistWindows est votre meilleure option, jusqu'à ce que quelque chose de plus général arrive.

Pour Windows, vous pouvez consulter: http://www.rgagnon.com/javadetails/java-0593.html

Linux peut tuyau les résultats de ps auxpar greptrop, ce qui rendrait le traitement / la recherche rapide et facile. Je suis sûr que vous pouvez également trouver quelque chose de similaire pour Windows.


Vous pouvez également consulter la liste des tâches plus en détail: technet.microsoft.com/en-us/library/bb491010.aspx
James Oravec

2

Le programme ci-dessous sera compatible avec Java 9+ uniquement version ...

Pour obtenir les informations 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);
    }
}

Pour tous les processus en cours,

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

Nous devons utiliser process.getOutputStream.close()sinon il sera verrouillé en boucle 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 

TASKLIST / v / FI "STATUS eq running" / FO "CSV" / FI "Username eq LHPL002 \ soft" / FI "MEMUSAGE gt 10000" / FI "Windowtitle ne N / A" / NH


0

Ceci est mon code pour une fonction qui récupère les tâches et obtient leurs noms, en les ajoutant également dans une liste accessible à partir d'une liste. Il crée des fichiers temporaires avec les données, lit les fichiers et obtient le nom de la tâche avec le suffixe .exe, et organise les fichiers à supprimer lorsque le programme est sorti avec System.exit (0), il masque également les processus utilisés pour obtenir les tâches et aussi java.exe afin que l'utilisateur ne puisse pas accidentellement tuer le processus qui exécute le programme tous ensemble.

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

J'ai également transformé ce code en un programme complet pour essayer de répliquer le gestionnaire de tâches intégré pour Windows 10, si quelqu'un est intéressé, je peux vous en envoyer une démo.
Dylan Wedman
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.