Bagaimana cara mendapatkan daftar jendela / proses yang terbuka saat ini dengan Java?

95

Apakah ada yang tahu bagaimana cara mendapatkan jendela terbuka saat ini atau proses mesin lokal menggunakan Java?

Apa yang saya coba lakukan adalah: daftar tugas terbuka saat ini, jendela atau proses terbuka, seperti di Windows Taskmanager, tetapi menggunakan pendekatan multi-platform - hanya menggunakan Java jika memungkinkan.

ramayac.dll
sumber

Jawaban:

105

Ini adalah pendekatan lain untuk mengurai daftar proses dari perintah " 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();
}

Jika Anda menggunakan Windows, maka Anda harus mengubah baris: "Process p = Runtime.getRun ..." dll ... (baris ke-3), untuk baris yang terlihat seperti ini:

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

Semoga infonya membantu!

ramayac.dll
sumber
bagaimana untuk mendapatkan waktu proses awal dan akhir waktu
Bucks
34
Di Windows, jalankan tasklist.exe /fo csv /nhuntuk mendapatkan daftar dalam format CSV, itu jauh lebih mudah untuk diurai.
Emmanuel Bourg
tetapi tidak menunjukkan nama stoples. Nama jar saya yang dapat dieksekusi adalah helloDemo.jar. tetapi tidak menunjukkan apa-apa untuk itu
Sumon Bappi
Mengapa tidak berhasil jika saya menambahkan | grep java? yaitu ps -elf | grep javatidak akan mengembalikan apa pun, tetapi ps -elfakan berfungsi seperti yang diharapkan.
Itay Moav -Malimovka
Perlu dicatat bahwa bit "khusus jendela" di bagian bawah tampaknya tidak diperlukan. Pada Windows 10, (.exec (Runtime/getRuntime) "tasklist"))(di Clojure, menggunakan Java-interop) mengembalikan tasklistproses dengan benar , bahkan tanpa menentukan direktori.
Carcigenicate
39

Akhirnya, dengan Java 9+ dimungkinkan dengan 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("-");
}

Keluaran:

    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.
sumber
Impor mana yang harus ditambahkan untuk bekerja dengan ProcessHandle?
Jordi
2
Kelas itu masuk java.langjadi tidak perlu mengimpor
Hugues M.
23

Di Windows ada alternatif menggunakan 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
sumber
Ini hanya memberikan nama perintah BUKAN seluruh baris perintah. Apakah ada cara untuk mendapatkan seluruh baris perintah?
Christopher Dancy
2
Anda bisa mendapatkan jalur lengkap dengan menelepon GetModuleFileName. Lihat stackoverflow.com/questions/7521693/… sebagai contoh.
Emmanuel Bourg
Satu-satunya masalah dengan ini adalah bahwa itu hanya memberikan jalur proses BUKAN seluruh baris perintah. Apakah ada cara untuk mendapatkan baris perintah lengkap dari proses tersebut (yaitu 'ant.bat -f helloWorld.ext')?
Christopher Dancy
bagaimana cara memeriksa proses tertentu seperti xyz.exe berjalan atau tidak?
unknownbits
@ChristopherDancy tidak yakin apakah Anda masih memerlukan jawaban tetapi untuk kelengkapan dan dan karena tidak disebutkan di sini: Winodws Managment Information Command-line (atau hanya wmic.exe) menyediakan cara untuk mengambil banyak informasi dari aplikasi yang sedang berjalan - WMIC PROCESSatau untuk membatasi output untuk proses tertentu: WMIC PROCESS WHERE name='theName'. Anda dapat menggunakan filter lebih lanjut untuk membatasi keluaran jika diperlukan. Baris perintah disertakan dalam kolom CommandLine dari tabel yang dikembalikan (= kolom ke-2)
Roman Vottner
9

Satu-satunya cara yang dapat saya pikirkan untuk melakukannya adalah dengan menjalankan aplikasi baris perintah yang melakukan pekerjaan untuk Anda dan kemudian menyaring hasilnya (seperti ps Linux dan daftar tugas Windows).

Sayangnya, itu berarti Anda harus menulis beberapa rutinitas parsing untuk membaca data dari keduanya.

Process proc = Runtime.getRuntime().exec ("tasklist.exe");
InputStream procOutput = proc.getInputStream ();
if (0 == proc.waitFor ()) {
    // TODO scan the procOutput for your data
}
jodonnell
sumber
1
Ya, saya sudah memikirkannya juga, tapi saya yakin itu bisa dilakukan dengan Java saja. Dan saya pikir saya akan lebih baik menggunakan "ps -aux" daripada top. Terima kasih atas jawaban cepatnya!
ramayac
Pada Windows, tasklistprogram dapat dikonfigurasi untuk mengeluarkan CSV :)
MauganRa
7

YAJSW (Yet Another Service Wrapper Java) sepertinya memiliki implementasi berbasis JNA dari antarmuka org.rzo.yajsw.os.TaskList untuk win32, linux, bsd dan solaris dan berada di bawah lisensi LGPL. Saya belum mencoba memanggil kode ini secara langsung, tetapi YAJSW bekerja dengan sangat baik ketika saya menggunakannya di masa lalu, jadi Anda tidak perlu terlalu khawatir.

SamWest
sumber
ternyata v12 + adalah lisensi ganda Apache / LGPL
harschware
5

Anda dapat dengan mudah mengambil daftar proses yang berjalan menggunakan 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
sumber
perpustakaan ini tampaknya sangat lambat ... apakah ada alasan untuk ini (atau apakah itu interop java + wmi umum di vbs?
Gobliins
2
Saya kira Anda berbicara tentang implementasi windows. Ya, biasanya pertanyaan WMI membutuhkan waktu. Seperti biasa, itu tergantung pada kasus penggunaan. Jika Anda perlu melakukan kueri setiap 10 md, ya, ini terlalu lambat.
profesor_falken
ya saya berbicara tentang menang, di linux saya melihat penggunaan "ps ... <options>" jadi saya kira itu harus jauh lebih cepat
Gobliins
Oke, jika Anda mau, Anda dapat membuat masalah di proyek github dan saya akhirnya akan melihat dan melihat apakah saya dapat meningkatkan kinerja di Win. Sebenarnya saya menggunakannya di Linux jadi saya tidak terlalu memperhatikan untuk memenangkan implementasi: -S
profesor_falken
Tidak apa-apa, tetapi yang saya cari: Dalam proses startTime Anda telah membatasi waktu yang diberikan untuk satu hari (jj: mm: dd) jika saya tidak salah. Apakah ada pilihan untuk mendapatkan juga tanggal + waktu (yyyy-mm-hh-hh: mm: ss)?
Gobliins
4

Tidak ada cara netral platform untuk melakukan ini. Dalam rilis 1.6 Java, kelas " Desktop " telah ditambahkan yang memungkinkan cara portabel untuk menjelajah, mengedit, mengirim, membuka, dan mencetak URI. Mungkin saja suatu saat kelas ini dapat diperluas untuk mendukung proses, tetapi saya meragukannya.

Jika Anda hanya ingin tahu tentang proses Java, Anda dapat menggunakan api java.lang.management untuk mendapatkan informasi utas / memori di JVM.

hazzen
sumber
4

Untuk windows saya gunakan berikut ini:

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

Ini mungkin berguna untuk aplikasi dengan JRE yang dibundel: Saya memindai nama folder tempat saya menjalankan aplikasi: jadi jika aplikasi Anda dijalankan dari:

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

maka Anda dapat mengetahui apakah itu sudah berjalan di J9, dengan:

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
sumber
3

Menggunakan kode untuk mengurai ps auxuntuk linux dan tasklistuntuk windows adalah pilihan terbaik Anda, sampai sesuatu yang lebih umum muncul.

Untuk Windows, Anda dapat merujuk ke: http://www.rgagnon.com/javadetails/java-0593.html

Linux juga dapat menyalurkan hasil ps auxmelalui grep, yang akan membuat pemrosesan / pencarian cepat dan mudah. Saya yakin Anda juga dapat menemukan sesuatu yang mirip untuk windows.

James Oravec
sumber
Anda mungkin ingin melihat daftar tugas lebih detail juga: technet.microsoft.com/en-us/library/bb491010.aspx
James Oravec
2

Program di bawah ini hanya akan kompatibel dengan versi Java 9+ ...

Untuk mendapatkan informasi 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);
    }
}

Untuk semua proses yang berjalan,

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

Kita harus menggunakan process.getOutputStream.close()jika tidak maka akan terkunci di while loop.

Jijo Joy
sumber
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
sumber
0

Ini adalah kode saya untuk fungsi yang mendapatkan tugas dan mendapatkan namanya, juga menambahkannya ke dalam daftar agar dapat diakses dari daftar. Ini membuat file temp dengan data, membaca file dan mendapatkan nama tugas dengan akhiran .exe, dan mengatur file yang akan dihapus ketika program telah keluar dengan System.exit (0), itu juga menyembunyikan proses yang digunakan untuk dapatkan tugas dan juga java.exe sehingga pengguna tidak dapat secara tidak sengaja mematikan proses yang menjalankan program secara bersamaan.

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
sumber
Saya juga telah membuat kode ini menjadi program lengkap untuk mencoba dan mereplikasi pengelola tugas bawaan untuk Windows 10, jika ada yang tertarik, saya dapat mengirimkan demo-nya.
Dylan Wedman