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.

ramayac
la source

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!

ramayac
la source
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
Hugues M.
la source
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);
    }
}
Emmanuel Bourg
la source
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
}
Jodonnell
la source
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.

SamWest
la source
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("------------------");
}
profesor_falken
la source
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.

hazzen
la source
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");
Stepan Yakovenko
la source
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");
}
wax_lyrical
la source
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.

James Oravec
la source
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());
        });
    }
}
Nallamachu
la source
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.

Jijo Joy
la source
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

Panchotiya Vipul
la source
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();
}
Dylan Wedman
la source
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