Java ile mevcut açık pencerelerin / işlemlerin bir listesini nasıl alabilirim?


97

Java kullanan yerel bir makinenin mevcut açık pencerelerini veya sürecini nasıl elde edeceğimi bilen var mı?

Yapmaya çalıştığım şey şudur: Windows Taskmanager'da olduğu gibi mevcut açık görevi, pencereleri veya işlemi açık olarak listeleyin, ancak çoklu platform yaklaşımı kullanarak - mümkünse yalnızca Java kullanarak.

Yanıtlar:


107

Bu, işlem listesini " ps -e " komutundan ayrıştırmak için başka bir yaklaşımdır :

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

Windows kullanıyorsanız, şuna benzer bir satır için "Process p = Runtime.getRun ..." vb ... (3. satır) satırını değiştirmelisiniz:

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

Umarım bilgi yardımcı olur!


işlemin başlangıç ​​ve bitiş zamanını alma
Bucks

34
Windows'ta tasklist.exe /fo csv /nhlisteyi CSV formatında almak için çalıştırın , ayrıştırması çok daha kolaydır.
Emmanuel Bourg

ancak kavanoz adını göstermiyor. Çalıştırılabilir jar adımım helloDemo.jar. ama bunun için hiçbir şey göstermiyor
Sumon Bappi

Bir | eklesem neden işe yaramıyor? grep java? yani ps -elf | grep javabir şey döndürmez, ancak ps -elfbeklendiği gibi çalışır.
Itay Moav -Malimovka

Alt kısımdaki "pencereye özgü" bitin gereksiz göründüğü unutulmamalıdır. Windows 10'da (.exec (Runtime/getRuntime) "tasklist"))(Clojure'da Java-birlikte çalışmayı kullanarak) tasklist, bir dizin belirtmeden bile işlemi doğru şekilde döndürür .
Carcigenicate

42

Son olarak, Java 9+ ile şunlarla mümkündür 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("-");
}

Çıktı:

    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

ProcessHandle ile çalışmak için hangi içe aktarımlar eklenmelidir?
Jordi

2
Bu sınıfta java.langbu yüzden ithalat gerekmiyor
Hugues M.

23

Windows'ta JNA kullanan bir alternatif var :

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

Bu yalnızca komut adını verir, komut satırının tamamına DEĞİL. Komut satırının tamamını almanın bir yolu var mı?
Christopher Dancy

2
Tam yolu arayarak alabilirsiniz GetModuleFileName. Örnek için stackoverflow.com/questions/7521693/… sayfasına bakın .
Emmanuel Bourg

Bununla birlikte tek sorun, komut satırının tamamını DEĞİL yalnızca işlemin yolunu vermesidir. İşlemin tam komut satırını almanın bir yolu var mı (yani 'ant.bat -f helloWorld.ext')?
Christopher Dancy

xyz.exe gibi belirli bir işlemin çalışıp çalışmadığını nasıl kontrol edebilirim?
unknownbits

@ChristopherDancy hala bir cevaba ihtiyacınız olup olmadığından emin değil, ancak tamlık için ve burada bahsedilmediği gibi: Winodws Yönetim Bilgi Komut satırı (veya sadece wmic.exe) çalışan uygulamaların birçok bilgisini almanın bir yolunu sağlar - WMIC PROCESSveya belirli bir süreç için çıkışını sınırlamak için: WMIC PROCESS WHERE name='theName'. Gerekirse çıktıyı sınırlandırmak için daha fazla filtre kullanabilirsiniz. Komut satırı, döndürülen tablonun CommandLine sütununa dahil edilmiştir (= 2. sütun)
Roman Vottner

9

Bunu yapmayı düşünebilmemin tek yolu, işi sizin için yapan bir komut satırı uygulamasını çağırmak ve ardından çıktıyı ekran karalaması yapmaktır (Linux'un ps ve Window'un görev listesi gibi).

Ne yazık ki bu, verileri her ikisinden de okumak için bazı ayrıştırma rutinleri yazmanız gerektiği anlamına gelir.

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

1
Evet, bunu da zaten düşünmüştüm, ama sadece Java ile yapılabilirdi. Ve sanırım top yerine "ps -aux" kullansam daha iyi olur. Hızlı cevap için teşekkürler!
ramayac

Windows'ta, tasklistprogram CSV çıktısı verecek şekilde yapılandırılabilir :)
MauganRa

7

YAJSW (Yine Bir Başka Java Hizmeti Sarıcı), win32, linux, bsd ve solaris için org.rzo.yajsw.os.TaskList arayüzünün JNA tabanlı uygulamalarına sahip gibi görünüyor ve bir LGPL lisansı altında. Bu kodu doğrudan aramayı denemedim, ancak YAJSW geçmişte kullandığımda gerçekten iyi çalışıyor, bu yüzden çok fazla endişelenmemelisin.


görünüşe göre v12 + Apache / LGPL ikili lisansıdır
harschware

5

JProcesses kullanarak çalışan işlemlerin listesini kolayca alabilirsiniz.

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

bu kütüphane çok yavaş görünüyor ... bunun bir nedeni var mı (yoksa vbs genelinde java + wmi birlikte çalışma mı?
Gobliins

2
Sanırım Windows uygulaması hakkında konuşuyorsunuz. Evet, normalde WMI sorguları biraz zaman alır. Her zaman olduğu gibi kullanım durumuna bağlıdır. Sorguyu her 10 ms'de bir yapmanız gerekiyorsa, evet, çok yavaştır.
profesor_falken

evet ben linux, kazanmak bahsettiği i çok daha hızlı olması gerektiği tahmin böylece "ps ... <seçenekleri>" kullanımını benekli
Gobliins

Tamam, isterseniz github projesinde bir sorun yaratabilirsiniz ve sonunda bir göz atıp Win'deki performansı iyileştirip iyileştiremeyeceğime bakacağım. Aslında onu Linux'ta kullandım, bu yüzden uygulamayı kazanmak için fazla dikkat etmedim: -S
profesor_falken

Sorun değil, ama aradığım şey: StartTime sürecinizde, hatalı değilsem verilen süreyi bir gün (ss: dd: ss) için sınırladınız. Ayrıca tarih + saati (yyyy-aa-gg-ss: dd: ss) alma seçeneği var mı?
Gobliins

4

Bunu yapmanın platformdan bağımsız bir yolu yoktur. Java'nın 1.6 sürümünde, URI'lara göz atmak, düzenlemek, postalamak, açmak ve yazdırmak için taşınabilir yollar sağlayan bir " Masaüstü " sınıfı eklendi. Bu sınıfın bir gün süreçleri destekleyecek şekilde genişletilmesi mümkündür, ancak bundan şüpheliyim.

Yalnızca Java süreçlerini merak ediyorsanız, JVM'de iş parçacığı / bellek bilgisi almak için java.lang.management api'sini kullanabilirsiniz .


4

Windows için şunları kullanıyorum:

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

Bu, paketlenmiş bir JRE'ye sahip uygulamalar için yararlı olabilir: Uygulamayı çalıştırdığım klasör adını tararım: yani, uygulama şuradan çalıştırılıyorsa:

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

o zaman J9'da zaten çalışıp çalışmadığını şu şekilde bulabilirsiniz:

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

ps auxLinux ve tasklistpencereler için ayrıştırmak için kod kullanmak , daha genel bir şey gelene kadar en iyi seçeneğinizdir.

Windows için şu adrese başvurabilirsiniz: http://www.rgagnon.com/javadetails/java-0593.html

Linux, sonuçları da ps auxyönlendirebilir grep, bu da işlemeyi / aramayı hızlı ve kolay hale getirir. Eminim pencereler için de benzer bir şey bulabilirsin.


Görev listesine daha ayrıntılı olarak da bakmak isteyebilirsiniz: technet.microsoft.com/en-us/library/bb491010.aspx
James Oravec

2

Aşağıdaki program yalnızca Java 9+ sürümüyle uyumlu olacaktır ...

CurrentProcess bilgilerini almak için,

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

Tüm çalışan işlemler için,

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

Kullanmalıyız, process.getOutputStream.close()aksi takdirde döngü sırasında kilitlenecektir.


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 "Kullanıcı Adı eq LHPL002 \ soft" / FI "MEMUSAGE gt 10000" / FI "Windowtitle ne N / A" / NH


0

Bu, görevleri alan ve adlarını alan ve ayrıca bir listeden erişilecek bir listeye ekleyen bir işlev için kodumdur. Verilerle birlikte geçici dosyalar oluşturur, dosyaları okur ve görev adını .exe sonekiyle alır ve program System.exit (0) ile çıktığında silinecek dosyaları düzenler, ayrıca kullanılan işlemleri gizler. görevleri ve ayrıca java.exe'yi alın, böylece kullanıcı programı hep birlikte çalıştıran işlemi yanlışlıkla öldüremez.

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

Ayrıca bu kodu Windows 10 için yerleşik görev yöneticisini denemek ve çoğaltmak için tam bir program haline getirdim, ilgilenen varsa size bunun bir demosunu gönderebilirim.
Dylan Wedman
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.