Làm cách nào để lấy danh sách các cửa sổ / quy trình đang mở hiện tại với Java?


94

Có ai biết cách lấy các cửa sổ hoặc quy trình đang mở hiện tại của một máy cục bộ bằng Java không?

Những gì tôi đang cố gắng làm là: liệt kê tác vụ đang mở hiện tại, các cửa sổ hoặc quy trình đang mở, như trong Windows Taskmanager, nhưng sử dụng phương pháp đa nền tảng - chỉ sử dụng Java nếu có thể.

Câu trả lời:


104

Đây là một cách tiếp cận khác để phân tích cú pháp danh sách tiến trình từ lệnh " 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();
}

Nếu bạn đang sử dụng Windows, thì bạn nên thay đổi dòng: "Process p = Runtime.getRun ..." v.v ... (dòng thứ 3), cho một dòng trông giống như sau:

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

Hy vọng thông tin giúp ích!


làm thế nào để có được thời gian quá trình bắt đầu và kết thúc thời gian
Bucks

34
Trên Windows, hãy chạy tasklist.exe /fo csv /nhđể nhận danh sách ở định dạng CSV, điều đó dễ dàng hơn để phân tích cú pháp.
Emmanuel Bourg

nhưng nó không hiển thị tên jar. Tên jar thực thi của tôi là helloDemo.jar. nhưng nó không hiển thị bất cứ điều gì cho nó
Triệu tập Bappi

Tại sao nó không hoạt động nếu tôi thêm dấu | grep java? tức là ps -elf | grep javasẽ không trả lại một thứ, nhưng ps -elfsẽ hoạt động như mong đợi.
Itay Moav -Malimovka

Cần lưu ý rằng bit "cửa sổ cụ thể" ở dưới cùng dường như là không cần thiết. Trên Windows 10, (.exec (Runtime/getRuntime) "tasklist"))(trong Clojure, sử dụng Java-interop) trả về tasklistquá trình một cách chính xác , ngay cả khi không chỉ định thư mục.
Chất gây ung thư

39

Cuối cùng, với Java 9+, có thể với 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("-");
}

Đầu ra:

    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

Nhập khẩu nào nên được thêm vào để hoạt động với ProcessHandle?
Jordi

2
Lớp đó là trong java.langnên không nhập khẩu cần thiết
Hugues M.

23

Trên Windows, có một giải pháp thay thế sử dụng 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);
    }
}

Điều này chỉ cung cấp cho tên lệnh KHÔNG phải toàn bộ dòng lệnh. Có cách nào để lấy toàn bộ dòng lệnh không?
Christopher Dancy

2
Bạn có thể nhận được đường dẫn đầy đủ bằng cách gọi GetModuleFileName. Xem stackoverflow.com/questions/7521693/… để làm ví dụ.
Emmanuel Bourg

Vấn đề duy nhất là nó chỉ đưa ra đường dẫn của tiến trình chứ KHÔNG phải toàn bộ dòng lệnh. Có cách nào để lấy dòng lệnh đầy đủ của quy trình (tức là 'ant.bat -f helloWorld.ext') không?
Christopher Dancy

làm thế nào để kiểm tra một quá trình cụ thể như xyz.exe đang chạy hay không?
xác định

@ChristopherDancy không chắc bạn có còn cần câu trả lời hay không nhưng về tính đầy đủ và vì nó cũng không được đề cập ở đây: Dòng lệnh thông tin quản lý Winodws (hoặc đơn giản là wmic.exe) cung cấp một cách để truy xuất nhiều thông tin về các ứng dụng đang chạy - WMIC PROCESShoặc để hạn chế đầu ra cho một quá trình cụ thể: WMIC PROCESS WHERE name='theName'. Bạn có thể sử dụng thêm các bộ lọc để giới hạn đầu ra nếu cần. Các dòng lệnh được bao gồm trong cột commandline của bảng trả lại (= cột thứ 2)
La Mã Vottner

9

Cách duy nhất tôi có thể nghĩ để làm điều đó là gọi một ứng dụng dòng lệnh thực hiện công việc cho bạn và sau đó màn hình hóa kết quả đầu ra (như danh sách tác vụ ps của Linux và Window).

Thật không may, điều đó có nghĩa là bạn sẽ phải viết một số quy trình phân tích cú pháp để đọc dữ liệu từ cả hai.

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

1
Đúng vậy, tôi cũng đã nghĩ về điều đó, nhưng tôi khó thực hiện được nó chỉ với Java. Và tôi nghĩ tôi sẽ tốt hơn nếu sử dụng "ps -aux" thay vì top. Cảm ơn vì sớm phản hồi!
ramayac 10/09/08

Trên Windows, tasklistchương trình có thể được cấu hình để đầu ra CSV :)
MauganRa

7

YAJSW (Yet Another Java Service Wrapper) có vẻ như nó có các triển khai dựa trên JNA của giao diện org.rzo.yajsw.os.TaskList cho win32, linux, bsd và solaris và có giấy phép LGPL. Tôi chưa thử gọi trực tiếp mã này, nhưng YAJSW hoạt động thực sự tốt khi tôi đã sử dụng nó trước đây, vì vậy bạn không nên quá lo lắng.


rõ ràng v12 + là giấy phép kép Apache / LGPL
harschware

5

Bạn có thể dễ dàng truy xuất danh sách các tiến trình đang chạy bằng 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("------------------");
}

thư viện này có vẻ là rất chậm ... là có một lý do cho điều này (hoặc là nó java chung + interop WMI trên vbs?
Gobliins

2
Tôi đoán bạn nói về việc triển khai windows. Có, thông thường các truy vấn WMI mất một chút thời gian. Như mọi khi, nó phụ thuộc vào trường hợp sử dụng. Nếu bạn cần thực hiện truy vấn sau mỗi 10 ms, thì có, nó quá chậm.
profesor_falken

vâng tôi đã nói về chiến thắng, trong linux tôi phát hiện việc sử dụng "ps ... <options>" vì vậy tôi đoán nó sẽ nhanh hơn nhiều
Gobliins

Ok, nếu bạn muốn, bạn có thể tạo sự cố trong dự án github và cuối cùng tôi sẽ xem xét và xem liệu tôi có thể cải thiện hiệu suất trong Win hay không. Trong thực tế, tôi sử dụng nó trên Linux vì vậy tôi không quan tâm nhiều đến chiến thắng thực hiện: -S
profesor_falken

Nó ổn, nhưng những gì tôi đang tìm kiếm: Trong startTime quy trình của bạn, bạn đã giới hạn thời gian nhất định trong một ngày (hh: mm: ss) nếu tôi không sai. Có tùy chọn nào để lấy cả ngày + giờ (yyyy-mm-dd-hh: mm: ss) không?
Gobliins

4

Không có cách nào trung lập với nền tảng để làm điều này. Trong phiên bản 1.6 của Java, một lớp " Máy tính để bàn " đã được thêm vào để cho phép các cách di động duyệt, chỉnh sửa, gửi thư, mở và in URI. Có thể một ngày nào đó lớp này có thể được mở rộng để hỗ trợ các quy trình, nhưng tôi nghi ngờ điều đó.

Nếu bạn chỉ tò mò về các quy trình Java, bạn có thể sử dụng api java.lang.management để lấy thông tin luồng / bộ nhớ trên JVM.


4

Đối với các cửa sổ tôi sử dụng như sau:

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

Điều này có thể hữu ích cho các ứng dụng có JRE đi kèm: Tôi quét tìm tên thư mục mà tôi đang chạy ứng dụng từ đó: vì vậy nếu ứng dụng của bạn đang thực thi từ:

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

thì bạn có thể tìm xem nó đã chạy trong J9 chưa, bằng cách:

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

Sử dụng mã để phân tích cú pháp ps auxcho linux và tasklistcho windows là những lựa chọn tốt nhất của bạn, cho đến khi có thứ gì đó tổng quát hơn.

Đối với windows, bạn có thể tham khảo: http://www.rgagnon.com/javadetails/java-0593.html

Linux có thể đường ống kết quả ps auxqua grepquá, mà sẽ làm cho chế biến / tìm kiếm nhanh chóng và dễ dàng. Tôi chắc rằng bạn cũng có thể tìm thấy thứ gì đó tương tự cho windows.


Bạn cũng có thể muốn xem danh sách tác vụ chi tiết hơn: technet.microsoft.com/en-us/library/bb491010.aspx
James Oravec

2

Chương trình dưới đây sẽ chỉ tương thích với phiên bản Java 9+ ...

Để nhận thông tin Quy trình hiện tại,

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

Đối với tất cả các quy trình đang chạy,

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

Chúng ta phải sử dụng process.getOutputStream.close()nếu không nó sẽ bị khóa trong vòng lặp while.


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


0

Đây là mã của tôi cho một chức năng nhận các nhiệm vụ và lấy tên của chúng, đồng thời thêm chúng vào một danh sách để được truy cập từ một danh sách. Nó tạo các tệp tạm thời với dữ liệu, đọc các tệp và nhận tên tác vụ với hậu tố .exe và sắp xếp các tệp sẽ bị xóa khi chương trình đã thoát bằng System.exit (0), nó cũng ẩn các quy trình đang được sử dụng để nhận các tác vụ và cả java.exe để người dùng không thể vô tình giết quá trình chạy chương trình cùng nhau.

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

Tôi cũng đã tạo mã này thành một chương trình đầy đủ để thử và sao chép trình quản lý tác vụ tích hợp sẵn cho Windows 10, nếu ai quan tâm, tôi có thể gửi cho bạn bản demo của nó.
Dylan Wedman
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.