จะรับรายการของ windows / กระบวนการที่เปิดอยู่ในปัจจุบันด้วย Java ได้อย่างไร


97

มีใครทราบบ้างว่าฉันจะรับหน้าต่างที่เปิดอยู่ในปัจจุบันหรือกระบวนการของเครื่องโลคัลโดยใช้ Java ได้อย่างไร

สิ่งที่ฉันพยายามทำคือ: แสดงรายการงานที่เปิดอยู่ในปัจจุบันหน้าต่างหรือกระบวนการที่เปิดอยู่เช่นใน Windows Taskmanager แต่ใช้วิธีการแบบหลายแพลตฟอร์มโดยใช้ Java เท่านั้นหากเป็นไปได้

คำตอบ:


107

นี่เป็นอีกวิธีหนึ่งในการแยกวิเคราะห์รายการกระบวนการจากคำสั่ง " 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();
}

หากคุณใช้ Windows คุณควรเปลี่ยนบรรทัด: "Process p = Runtime.getRun ... " ฯลฯ ... (บรรทัดที่ 3) สำหรับบรรทัดที่มีลักษณะดังนี้:

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

หวังว่าข้อมูลจะช่วยได้!


วิธีรับเวลาเริ่มต้นและเวลาสิ้นสุดของกระบวนการ
Bucks

34
ใน Windows ให้เรียกใช้tasklist.exe /fo csv /nhเพื่อรับรายการในรูปแบบ CSV ซึ่งง่ายกว่ามากในการแยกวิเคราะห์
Emmanuel Bourg

แต่ไม่แสดงชื่อโถ ชื่อขวดปฏิบัติการของฉันคือ helloDemo.jar แต่มันไม่ได้แสดงอะไรเลย
Sumon Bappi

ทำไมถึงใช้ไม่ได้ถ้าฉันเพิ่ม | grep java? เช่นps -elf | grep javaจะไม่คืนค่า แต่ps -elfจะทำงานตามที่คาดไว้
Itay Moav -Malimovka

ควรสังเกตว่าบิต "เฉพาะหน้าต่าง" ที่ด้านล่างดูเหมือนจะไม่จำเป็น บน Windows 10 (.exec (Runtime/getRuntime) "tasklist"))(ใน Clojure โดยใช้ Java-interop) จะส่งคืนtasklistกระบวนการอย่างถูกต้องแม้ว่าจะไม่ได้ระบุไดเร็กทอรีก็ตาม
Carcigenicate

42

สุดท้ายด้วย Java 9+ สามารถทำได้ด้วย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("-");
}

เอาท์พุต:

    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
Jordi

2
ชั้นเรียนjava.langนั้นไม่จำเป็นต้องนำเข้า
Hugues M.

23

ใน Windows มีทางเลือกอื่นโดยใช้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);
    }
}

สิ่งนี้ทำให้ชื่อคำสั่งเท่านั้นไม่ใช่บรรทัดคำสั่งทั้งหมด มีวิธีรับบรรทัดคำสั่งทั้งหมดหรือไม่?
Christopher Dancy

2
GetModuleFileNameคุณจะได้รับเส้นทางแบบเต็มโดยการเรียก ดูตัวอย่างstackoverflow.com/questions/7521693/…
Emmanuel Bourg

ปัญหาเดียวที่มีคือมันให้เฉพาะเส้นทางของกระบวนการไม่ใช่บรรทัดคำสั่งทั้งหมด มีวิธีรับบรรทัดคำสั่งแบบเต็มของกระบวนการ (เช่น 'ant.bat -f helloWorld.ext') หรือไม่
Christopher Dancy

วิธีตรวจสอบกระบวนการเฉพาะเช่น xyz.exe กำลังทำงานอยู่หรือไม่?
Unknownbits

@ChristopherDancy ไม่แน่ใจว่าคุณยังต้องการคำตอบหรือไม่ แต่เพื่อความสมบูรณ์และเนื่องจากไม่ได้กล่าวไว้ที่นี่เช่นกัน: บรรทัดคำสั่งข้อมูลการจัดการ Winodws (หรือเพียงแค่ wmic.exe)เป็นวิธีการดึงข้อมูลจำนวนมากของแอปพลิเคชันที่ใช้งานอยู่WMIC PROCESSหรือ เพื่อ จำกัด เอาต์พุตสำหรับกระบวนการเฉพาะ: WMIC PROCESS WHERE name='theName'. คุณสามารถใช้ตัวกรองเพิ่มเติมเพื่อ จำกัด เอาต์พุตได้หากจำเป็น บรรทัดคำสั่งรวมอยู่ในคอลัมน์ CommandLine ของตารางที่ส่งคืน (= คอลัมน์ที่ 2)
Roman Vottner

9

วิธีเดียวที่ฉันคิดได้คือการเรียกใช้แอปพลิเคชันบรรทัดคำสั่งที่ทำงานให้คุณจากนั้นคัดลอกผลลัพธ์ (เช่น ps ของ Linux และรายการงานของ Window)

น่าเสียดายนั่นหมายความว่าคุณจะต้องเขียนขั้นตอนการแยกวิเคราะห์เพื่ออ่านข้อมูลจากทั้งสองอย่าง

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

1
ใช่ฉันก็คิดเกี่ยวกับเรื่องนั้นอยู่แล้ว แต่ฉันยากที่จะทำได้ด้วย Java เท่านั้น และฉันคิดว่าฉันควรใช้ "ps -aux" แทนด้านบน ขอบคุณสำหรับคำตอบด่วน!
ramayac

ใน Windows tasklistโปรแกรมสามารถกำหนดค่าให้ส่งออก CSV ได้ :)
MauganRa

7

YAJSW (ยังมี Java Service Wrapper อีกตัว) ดูเหมือนว่าจะมีการใช้งานตาม JNA ของอินเทอร์เฟซ org.rzo.yajsw.os.TaskList สำหรับ win32, linux, bsd และ solaris และอยู่ภายใต้ใบอนุญาต LGPL ฉันไม่ได้ลองโทรหารหัสนี้โดยตรง แต่ YAJSW ใช้งานได้ดีจริงๆเมื่อฉันเคยใช้รหัสนี้มาก่อนดังนั้นคุณไม่ควรกังวลมากเกินไป


เห็นได้ชัดว่า v12 + เป็นใบอนุญาตคู่ Apache / LGPL
harschware

5

คุณสามารถดึงรายการของกระบวนการที่กำลังทำงานอยู่โดยใช้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("------------------");
}

ห้องสมุดนี้ดูเหมือนจะช้ามาก ... มีเหตุผลสำหรับสิ่งนี้ (หรือว่า java + wmi interop ทั่วไปข้าม vbs?
Gobliins

2
ฉันเดาว่าคุณพูดถึงการใช้งาน windows ใช่ปกติการสืบค้น WMI จะใช้เวลาพอสมควร และเช่นเคยขึ้นอยู่กับกรณีการใช้งาน หากคุณจำเป็นต้องดำเนินการค้นหาทุก ๆ 10 มิลลิวินาทีใช่มันช้าเกินไป
profesor_falken

ใช่ฉันกำลังพูดถึง win ใน linux ฉันเห็นการใช้ "ps ... <options>" ดังนั้นฉันคิดว่ามันน่าจะเร็วกว่ามาก
Gobliins

โอเคถ้าคุณต้องการคุณสามารถสร้างปัญหาในโปรเจ็กต์ github และในที่สุดฉันจะดูและดูว่าฉันสามารถปรับปรุงประสิทธิภาพใน Win ได้หรือไม่ อันที่จริงฉันใช้มันบน Linux ดังนั้นฉันจึงไม่ได้ให้ความสนใจมากนักที่จะชนะการนำไปใช้: -S
profesor_falken

เป็นเรื่องปกติ แต่สิ่งที่ฉันกำลังมองหา: ในกระบวนการเริ่มต้นเวลาของคุณคุณได้ จำกัด เวลาที่กำหนดไว้หนึ่งวัน (hh: mm: ss) ถ้าฉันไม่ผิด มีตัวเลือกใดบ้างในการรับวันที่ + เวลา (yyyy-mm-dd-hh: mm: ss)
Gobliins

4

ไม่มีวิธีที่เป็นกลางของแพลตฟอร์มในการทำเช่นนี้ ใน Java รุ่น 1.6 มีการเพิ่มคลาส " เดสก์ท็อป " ซึ่งช่วยให้สามารถเรียกดูแก้ไขส่งเมลเปิดและพิมพ์ URI ได้แบบพกพา เป็นไปได้ว่าสักวันชั้นเรียนนี้อาจจะขยายไปสู่กระบวนการสนับสนุน แต่ฉันสงสัย

หากคุณอยากรู้อยากเห็นเฉพาะในกระบวนการ Java คุณสามารถใช้java.lang.management api เพื่อรับข้อมูลเธรด / หน่วยความจำบน JVM


4

สำหรับ windows ฉันใช้สิ่งต่อไปนี้:

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

สิ่งนี้อาจมีประโยชน์สำหรับแอพที่มี JRE ที่แถมมา: ฉันสแกนหาชื่อโฟลเดอร์ที่ฉันเรียกใช้แอพพลิเคชั่นจาก: ดังนั้นหากคุณกำลังเรียกใช้แอพพลิเคชั่นจาก:

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

จากนั้นคุณจะพบว่ามันทำงานใน J9 ​​แล้วหรือไม่โดย:

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 auxสำหรับ linux และtasklistสำหรับ windows เป็นตัวเลือกที่ดีที่สุดของคุณจนกว่าจะมีบางสิ่งที่ทั่วไปเข้ามา

สำหรับ windows คุณสามารถอ้างอิง: http://www.rgagnon.com/javadetails/java-0593.html

Linux สามารถไพพ์ผลลัพธ์ของ ps auxผ่านได้grepเช่นกันซึ่งจะทำให้การประมวลผล / ค้นหาง่ายและรวดเร็ว ฉันแน่ใจว่าคุณสามารถหาสิ่งที่คล้ายกันสำหรับ windows ได้เช่นกัน


คุณอาจต้องการดูรายละเอียดเพิ่มเติมในรายการงานด้วย: technet.microsoft.com/en-us/library/bb491010.aspx
James Oravec

2

โปรแกรมด้านล่างนี้จะเข้ากันได้กับJava 9+เวอร์ชันเท่านั้น ...

หากต้องการรับข้อมูล 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);
    }
}

สำหรับกระบวนการทำงานทั้งหมด

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

เราต้องใช้process.getOutputStream.close()มิฉะนั้นมันจะถูกล็อคในขณะที่วน


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 "ชื่อผู้ใช้ eq LHPL002 \ soft" / FI "MEMUSAGE gt 10000" / FI "Windowtitle ne N / A" / NH


0

นี่คือรหัสของฉันสำหรับฟังก์ชั่นที่รับงานและรับชื่อของพวกเขารวมทั้งเพิ่มลงในรายการเพื่อเข้าถึงจากรายการ มันสร้างไฟล์ temp ด้วยข้อมูลอ่านไฟล์และรับชื่องานด้วยคำต่อท้าย. exe และจัดเรียงไฟล์ที่จะลบเมื่อโปรแกรมออกจาก System.exit (0) นอกจากนี้ยังซ่อนกระบวนการที่ใช้ในการ รับงานและ java.exe เพื่อให้ผู้ใช้ไม่สามารถฆ่ากระบวนการที่รันโปรแกรมทั้งหมดเข้าด้วยกันโดยไม่ได้ตั้งใจ

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

ฉันได้สร้างรหัสนี้เป็นโปรแกรมเต็มรูปแบบเพื่อลองทำซ้ำตัวจัดการงานในตัวสำหรับ Windows 10 หากใครสนใจฉันสามารถส่งตัวอย่างให้คุณได้
Dylan Wedman
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.