Wie erhalte ich eine Liste der aktuell geöffneten Fenster / Prozesse mit Java?

94

Weiß jemand, wie ich die aktuell geöffneten Fenster oder den Prozess eines lokalen Computers mit Java erhalte?

Ich versuche Folgendes: Liste der aktuell geöffneten Aufgaben, Fenster oder geöffneten Prozesse wie im Windows Taskmanager auf, jedoch mit einem plattformübergreifenden Ansatz - wenn möglich nur mit Java.

Ramayac
quelle

Antworten:

104

Dies ist ein weiterer Ansatz, um die Prozessliste mit dem Befehl " ps -e " zu analysieren :

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

Wenn Sie Windows verwenden, sollten Sie die Zeile "Process p = Runtime.getRun ..." etc ... (3. Zeile) für eine Zeile ändern, die folgendermaßen aussieht:

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

Hoffe die Info hilft!

Ramayac
quelle
wie die Prozess Startzeit und die Endzeit zu bekommen
Bucks
34
Führen Sie unter Windows aus, tasklist.exe /fo csv /nhum die Liste im CSV-Format abzurufen. Dies ist viel einfacher zu analysieren.
Emmanuel Bourg
aber es zeigt nicht den Namen des Glases. Mein ausführbarer JAR-Name ist helloDemo.jar. aber es zeigt nichts dafür
Sumon Bappi
Warum würde es nicht funktionieren, wenn ich ein | hinzufüge? grep java? dh ps -elf | grep javawird nichts zurückgeben, ps -elfwürde aber wie erwartet funktionieren.
Itay Moav-Malimovka
Es ist zu beachten, dass das "Windows-spezifische" Bit unten unnötig erscheint. Unter Windows 10 (.exec (Runtime/getRuntime) "tasklist"))(in Clojure mit Java-Interop) wird der tasklistProzess korrekt zurückgegeben, auch ohne Angabe eines Verzeichnisses.
Carcigenicate
39

Schließlich ist es mit Java 9+ möglich mit 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("-");
}

Ausgabe:

    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.
quelle
Welche Importe sollten hinzugefügt werden, um mit ProcessHandle zu arbeiten?
Jordi
2
Diese Klasse ist in java.langso kein Import erforderlich
Hugues M.
23

Unter Windows gibt es eine Alternative mit 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
quelle
Dies gibt nur den Befehlsnamen NICHT die gesamte Befehlszeile. Gibt es eine Möglichkeit, die gesamte Befehlszeile abzurufen?
Christopher Dancy
2
Sie können den vollständigen Pfad erhalten, indem Sie anrufen GetModuleFileName. Ein Beispiel finden Sie unter stackoverflow.com/questions/7521693/… .
Emmanuel Bourg
Das einzige Problem dabei ist, dass nur der Pfad des Prozesses angegeben wird, NICHT die gesamte Befehlszeile. Gibt es eine Möglichkeit, die vollständige Befehlszeile des Prozesses abzurufen (z. B. 'ant.bat -f helloWorld.ext')?
Christopher Dancy
Wie überprüfe ich, ob ein bestimmter Prozess wie xyz.exe ausgeführt wird oder nicht?
Unbekannte Bits
@ChristopherDancy ist sich nicht sicher, ob Sie noch eine Antwort benötigen, aber der Vollständigkeit halber und und wie hier auch nicht erwähnt: Die Winodws Managment Information Command-Line (oder einfach wmic.exe) bietet eine Möglichkeit, viele Informationen über laufende Anwendungen abzurufen - WMIC PROCESSoder um die Ausgabe für einen bestimmten Prozess einzuschränken : WMIC PROCESS WHERE name='theName'. Sie können weitere Filter verwenden, um die Ausgabe bei Bedarf zu begrenzen. Die Befehlszeile ist in der CommandLine-Spalte der zurückgegebenen Tabelle enthalten (= 2. Spalte)
Roman Vottner
9

Ich kann mir das nur vorstellen, indem ich eine Befehlszeilenanwendung aufrufe, die die Arbeit für Sie erledigt, und dann die Ausgabe auf dem Bildschirm abkratzt (wie die ps- und Windows-Aufgabenliste von Linux).

Leider bedeutet dies, dass Sie einige Parsing-Routinen schreiben müssen, um die Daten von beiden zu lesen.

Process proc = Runtime.getRuntime().exec ("tasklist.exe");
InputStream procOutput = proc.getInputStream ();
if (0 == proc.waitFor ()) {
    // TODO scan the procOutput for your data
}
Jodonnell
quelle
1
Ja, darüber habe ich auch schon nachgedacht, aber ich habe es schwer, dass es nur mit Java geht. Und ich denke, ich wäre besser, "ps -aux" anstelle von top zu verwenden. Danke für die schnelle Antwort!
Ramayac
Unter Windows kann das tasklistProgramm für die Ausgabe von CSV konfiguriert werden :)
MauganRa
7

YAJSW (ein weiterer Java Service Wrapper) scheint JNA-basierte Implementierungen seiner org.rzo.yajsw.os.TaskList-Schnittstelle für Win32, Linux, BSD und Solaris zu haben und unterliegt einer LGPL-Lizenz. Ich habe nicht versucht, diesen Code direkt aufzurufen, aber YAJSW funktioniert wirklich gut, wenn ich ihn in der Vergangenheit verwendet habe, sodass Sie sich nicht zu viele Sorgen machen sollten.

SamWest
quelle
anscheinend v12 + ist Apache / LGPL Doppellizenz
harschware
5

Mit jProcesses können Sie die Liste der ausgeführten Prozesse einfach abrufen

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
quelle
Diese Bibliothek scheint sehr langsam zu sein ... gibt es einen Grund dafür (oder ist es allgemein Java + WMI Interop über VBS?
Gobliins
2
Ich denke, Sie sprechen über die Windows-Implementierung. Ja, normalerweise dauern WMI-Abfragen einige Zeit. Wie immer kommt es auf den Anwendungsfall an. Wenn Sie die Abfrage alle 10 ms durchführen müssen, ist sie zu langsam.
profesor_falken
Ja, ich habe über Win gesprochen. Unter Linux habe ich die Verwendung von "ps ... <Optionen>" entdeckt, also denke ich, dass es viel schneller sein sollte
Gobliins
Ok, wenn Sie möchten, können Sie ein Problem im Github-Projekt erstellen, und ich werde irgendwann nachsehen, ob ich die Leistung in Win verbessern kann. Tatsächlich habe ich es unter Linux verwendet, also habe ich nicht viel darauf geachtet, die Implementierung zu gewinnen: -S
profesor_falken
Es ist in Ordnung, aber was ich gesucht habe: In Ihrem Prozess startTime haben Sie die angegebene Zeit für einen Tag (hh: mm: ss) begrenzt, wenn ich mich nicht irre. Gibt es eine Option, um auch Datum und Uhrzeit abzurufen (JJJJ-MM-TT-HH: MM: SS)?
Gobliins
4

Es gibt keine plattformneutrale Möglichkeit, dies zu tun. In der Version 1.6 von Java wurde eine " Desktop " -Klasse hinzugefügt, die tragbare Möglichkeiten zum Durchsuchen, Bearbeiten, Versenden, Öffnen und Drucken von URIs ermöglicht. Es ist möglich, dass diese Klasse eines Tages erweitert wird, um Prozesse zu unterstützen, aber ich bezweifle es.

Wenn Sie nur neugierig auf Java-Prozesse sind, können Sie die API java.lang.management verwenden, um Thread- / Speicherinformationen in der JVM abzurufen.

Hazzen
quelle
4

Für Windows verwende ich Folgendes:

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

Dies kann für Apps mit einer gebündelten JRE nützlich sein: Ich suche nach dem Ordnernamen, von dem aus ich die Anwendung ausführe: Wenn Ihre Anwendung also ausgeführt wird von:

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

Dann können Sie feststellen, ob es bereits in J9 ausgeführt wird, indem Sie:

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");
}
wachs_lyrisch
quelle
3

Das Parsen von Code ps auxfür Linux und tasklistWindows ist die beste Option, bis etwas Allgemeineres hinzukommt.

Für Windows können Sie auf Folgendes verweisen: http://www.rgagnon.com/javadetails/java-0593.html

Linux kann die Ergebisse der ps auxdurch grepAuch die Verarbeitung machen würde / schnelle und einfache Suche. Ich bin sicher, dass Sie auch für Windows etwas Ähnliches finden können.

James Oravec
quelle
Vielleicht möchten Sie sich die Aufgabenliste auch genauer ansehen: technet.microsoft.com/en-us/library/bb491010.aspx
James Oravec
2

Das folgende Programm ist nur mit der Java 9+ Version kompatibel ...

Um die CurrentProcess-Informationen abzurufen,

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

Für alle laufenden Prozesse

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

Wir müssen verwenden, process.getOutputStream.close()sonst wird es in while-Schleife gesperrt.

Jijo Joy
quelle
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 

AUFGABENLISTE / v / FI "STATUS eq läuft" / FO "CSV" / FI "Benutzername eq LHPL002 \ soft" / FI "MEMUSAGE gt 10000" / FI "Fenstertitel ne N / A" / NH

Panchotiya Vipul
quelle
0

Dies ist mein Code für eine Funktion, die die Aufgaben und ihre Namen abruft und sie auch zu einer Liste hinzufügt, auf die über eine Liste zugegriffen werden kann. Es erstellt temporäre Dateien mit den Daten, liest die Dateien und erhält den Aufgabennamen mit dem Suffix .exe und ordnet die zu löschenden Dateien an, wenn das Programm mit System.exit (0) beendet wurde. Außerdem werden die verwendeten Prozesse ausgeblendet Holen Sie sich die Aufgaben und auch java.exe, damit der Benutzer den Prozess, der das Programm insgesamt ausführt, nicht versehentlich beenden kann.

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
quelle
Ich habe diesen Code auch zu einem vollständigen Programm gemacht, um zu versuchen, den integrierten Task-Manager für Windows 10 zu replizieren. Wenn jemand interessiert ist, kann ich Ihnen eine Demo davon senden.
Dylan Wedman