¿Cómo obtener una lista de las ventanas / procesos abiertos actuales con Java?

95

¿Alguien sabe cómo obtengo las ventanas abiertas actuales o el proceso de una máquina local usando Java?

Lo que estoy tratando de hacer es: enumerar la tarea abierta actual, las ventanas o el proceso abierto, como en el Administrador de tareas de Windows, pero usando un enfoque multiplataforma, usando solo Java si es posible.

ramayac
fuente

Respuestas:

105

Este es otro enfoque para analizar la lista de procesos desde el comando " 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 está utilizando Windows, debe cambiar la línea: "Process p = Runtime.getRun ..." etc ... (tercera línea), por una que se vea así:

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

¡Espero que la información ayude!

ramayac
fuente
cómo obtener la hora de inicio y finalización del proceso
Bucks
34
En Windows, ejecute tasklist.exe /fo csv /nhpara obtener la lista en formato CSV, es mucho más fácil de analizar.
Emmanuel Bourg
pero no muestra el nombre del tarro. Mi nombre de jar ejecutable es helloDemo.jar. pero no muestra nada para ello
Sumon Bappi
¿Por qué no funcionaría si agrego un | grep java? es decir ps -elf | grep java, no devolverá nada, pero ps -elffuncionaría como se esperaba.
Itay Moav -Malimovka
Cabe señalar que el bit "específico de Windows" en la parte inferior parece ser innecesario. En Windows 10, (.exec (Runtime/getRuntime) "tasklist"))(en Clojure, usando Java-interop) devuelve correctamente el tasklistproceso, incluso sin especificar un directorio.
Carcigenicate
39

Finalmente, con Java 9+ es posible con 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("-");
}

Salida:

    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.
fuente
¿Qué importaciones se deben agregar para trabajar con ProcessHandle?
Jordi
2
Esa clase está en, java.langpor lo que no es necesario importar
Hugues M.
23

En Windows hay una alternativa que usa 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
fuente
Esto solo da el nombre del comando, NO toda la línea de comando. ¿Hay alguna forma de obtener la línea de comandos completa?
Christopher Dancy
2
Puede obtener la ruta completa llamando GetModuleFileName. Consulte stackoverflow.com/questions/7521693/… para ver un ejemplo.
Emmanuel Bourg
El único problema con esto es que solo proporciona la ruta del proceso, NO la línea de comandos completa. ¿Hay alguna forma de obtener la línea de comandos completa del proceso (es decir, 'ant.bat -f helloWorld.ext')?
Christopher Dancy
¿Cómo comprobar si un proceso en particular como xyz.exe se está ejecutando o no?
unknownbits
@ChristopherDancy no estoy seguro de si aún necesita una respuesta, pero para completar y, como tampoco se mencionó aquí: La línea de comandos de información de administración de Winodws (o simplemente wmic.exe) proporciona una forma de recuperar mucha información de las aplicaciones en ejecución, WMIC PROCESSo para restringir la salida para un proceso específico: WMIC PROCESS WHERE name='theName'. Puede utilizar más filtros para limitar la salida si es necesario. La línea de comando se incluye en la columna CommandLine de la tabla devuelta (= segunda columna)
Roman Vottner
9

La única forma en que puedo pensar en hacerlo es invocando una aplicación de línea de comandos que hace el trabajo por usted y luego escaneando la salida (como ps de Linux y la lista de tareas de Windows).

Desafortunadamente, eso significará que tendrá que escribir algunas rutinas de análisis para leer los datos de ambos.

Process proc = Runtime.getRuntime().exec ("tasklist.exe");
InputStream procOutput = proc.getInputStream ();
if (0 == proc.waitFor ()) {
    // TODO scan the procOutput for your data
}
Jodonnell
fuente
1
Sí, ya pensé en eso también, pero creo que solo se podría hacer con Java. Y creo que sería mejor usar "ps -aux" en lugar de top. ¡Gracias por la rápida respuesta!
ramayac
En Windows, el tasklistprograma se puede configurar para generar CSV :)
MauganRa
7

YAJSW (Yet Another Java Service Wrapper) parece que tiene implementaciones basadas en JNA de su interfaz org.rzo.yajsw.os.TaskList para win32, linux, bsd y solaris y tiene una licencia LGPL. No he intentado llamar a este código directamente, pero YAJSW funciona muy bien cuando lo he usado en el pasado, por lo que no debería tener demasiadas preocupaciones.

SamWest
fuente
aparentemente v12 + es una licencia dual Apache / LGPL
harschware
5

Puede recuperar fácilmente la lista de procesos en ejecución utilizando 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
fuente
esta biblioteca parece ser muy lenta ... ¿hay alguna razón para esto (o es una interoperabilidad general de java + wmi en vbs?
Gobliins
2
Supongo que hablas de implementación de Windows. Sí, normalmente las consultas de WMI llevan algún tiempo. Como siempre, depende del caso de uso. Si necesita realizar la consulta cada 10 ms, sí, es demasiado lento.
profesor_falken
sí, estaba hablando de win, en Linux vi el uso de "ps ... <options>", así que supongo que debería ser mucho más rápido
Gobliins
Ok, si quieres puedes crear un problema en el proyecto github y eventualmente echaré un vistazo y veré si puedo mejorar el rendimiento en Win. De hecho lo usé en Linux, así que no presté mucha atención a ganar la implementación: -S
profesor_falken
Está bien, pero lo que estaba buscando: en su proceso startTime, ha limitado el tiempo dado para un día (hh: mm: ss) si no me equivoco. ¿Existe alguna opción para obtener también la fecha y la hora (aaaa-mm-dd-hh: mm: ss)?
Gobliins
4

No hay una forma neutral de plataforma de hacer esto. En la versión 1.6 de Java, se agregó una clase " Escritorio " que permite formas portátiles de navegar, editar, enviar, abrir e imprimir URI. Es posible que esta clase algún día se amplíe para apoyar procesos, pero lo dudo.

Si solo tiene curiosidad por los procesos de Java, puede utilizar la api java.lang.management para obtener información de hebras / memoria en la JVM.

hazzen
fuente
4

Para Windows utilizo lo siguiente:

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
fuente
4

Esto podría ser útil para aplicaciones con un JRE incluido: busco el nombre de la carpeta desde la que estoy ejecutando la aplicación: así que si su aplicación se está ejecutando desde:

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

luego puede encontrar si ya se está ejecutando en J9, por:

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");
}
cera_lírica
fuente
3

Usar código para analizar ps auxpara Linux y tasklistWindows son sus mejores opciones, hasta que aparezca algo más general.

Para Windows, puede hacer referencia a: http://www.rgagnon.com/javadetails/java-0593.html

Tubo de lata Linux los resultados de ps auxa través grepdemasiado, lo que haría procesamiento / búsqueda rápida y fácil. Estoy seguro de que también puedes encontrar algo similar para Windows.

James Oravec
fuente
Es posible que también desee ver la lista de tareas con más detalle: technet.microsoft.com/en-us/library/bb491010.aspx
James Oravec
2

El siguiente programa será compatible solo con la versión de Java 9+ ...

Para obtener la información de 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);
    }
}

Para todos los procesos en ejecución,

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

Tenemos que usarlo, de lo process.getOutputStream.close()contrario se bloqueará en el bucle while.

Jijo Joy
fuente
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 "Nombre de usuario eq LHPL002 \ soft" / FI "MEMUSAGE gt 10000" / FI "Windowtitle ne N / A" / NH

Panchotiya Vipul
fuente
0

Este es mi código para una función que obtiene las tareas y obtiene sus nombres, y también las agrega a una lista para acceder desde una lista. Crea archivos temporales con los datos, lee los archivos y obtiene el nombre de la tarea con el sufijo .exe, y organiza los archivos para eliminarlos cuando el programa ha salido con System.exit (0), también oculta los procesos que se utilizan para obtenga las tareas y también java.exe para que el usuario no pueda matar accidentalmente el proceso que ejecuta el programa todos juntos.

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
fuente
También convertí este código en un programa completo para intentar replicar el administrador de tareas incorporado para Windows 10, si alguien está interesado, puedo enviarle una demostración.
Dylan Wedman