Javaで現在開いているウィンドウ/プロセスのリストを取得するにはどうすればよいですか?


94

Javaを使用してローカルマシンの現在開いているウィンドウまたはプロセスを取得する方法を知っている人はいますか?

私がやろうとしていることは、Windowsタスクマネージャーのように、現在開いているタスク、ウィンドウ、または開いているプロセスを一覧表示することですが、マルチプラットフォームのアプローチを使用します-可能であればJavaのみを使用します。

回答:


104

これは、コマンド「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

ただし、jar名は表示されません。私の実行可能なjar名はhelloDemo.jarです。しかし、何も表示されていません
Sumon Bappi

|を追加すると機能しないのはなぜですか。grep java?つまりps -elf | grep java、物は返されませんがps -elf、期待どおりに動作します。
Itay Moav -Malimovka 2016年

下部にある「ウィンドウ固有」ビットは不要に見えることに注意してください。Windows 10 (.exec (Runtime/getRuntime) "tasklist"))(ClojureではJava-interopを使用)ではtasklist、ディレクトリを指定しなくても、プロセスが正しく返されます。
発がん性物質2017年

39

最後に、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を使用するには、どのインポートを追加する必要がありますか?
ジョルディ

2
そのクラスはであるjava.lang何のインポートが必要ありませんので、
ユーグ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);
    }
}

これにより、コマンドライン全体ではなく、コマンド名のみが表示されます。コマンドライン全体を取得する方法はありますか?
クリストファーダンシー2013年

2
を呼び出すことでフルパスを取得できますGetModuleFileName。例については、stackoverflow.com / questions / 7521693 /…を参照してください。
Emmanuel Bourg

これに関する唯一の問題は、コマンドライン全体ではなく、プロセスのパスのみを提供することです。プロセスの完全なコマンドラインを取得する方法はありますか(つまり、「ant.bat -f helloWorld.ext」)。
クリストファーダンシー2013年

xyz.exeなどの特定のプロセスが実行されているかどうかを確認する方法
unknownbits 2013

@ChristopherDancyまだ答えが必要かどうかはわかりませんが、完全性のため、そしてここでも言及されていません。Winodws管理情報コマンドライン(または単にwmic.exe)は、実行中のアプリケーションの多くの情報を取得する方法を提供します- WMIC PROCESSまたは特定のプロセスの出力を制限するには:WMIC PROCESS WHERE name='theName'。必要に応じて、さらにフィルターを使用して出力を制限できます。コマンドラインは、返されるテーブルのCommandLine列(= 2番目の列)に含まれています
Roman Vottner

9

私がそれを行うと考えることができる唯一の方法は、あなたのために仕事をするコマンドラインアプリケーションを呼び出してから、出力をスクリーンスクレイピングすることです(Linuxのpsや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だけで実行できるとは思いませんでした。そして、topの代わりに "ps -aux"を使用するほうがよいと思います。素早い回答ありがとうございます!
ramayac 2008

Windowsでは、tasklistプログラムはCSVを出力するように設定できます:)
MauganRa

7

YAJSW(Yet Another Java Service Wrapper)は、win32、linux、bsd、solaris用のorg.rzo.yajsw.os.TaskListインターフェースのJNAベースの実装があり、LGPLライセンスの下にあるようです。私はこのコードを直接呼び出そうとはしていませんが、YAJSWを過去に使用したことがある場合は非常にうまく機能するので、あまり心配する必要はありません。


どうやらv12 +はApache / LGPLのデュアルライセンスです
harschware '25

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

このライブラリは非常に遅いようです...これには理由がありますか
vbs

2
Windowsの実装について話したと思います。はい、通常、WMIクエリには時間がかかります。いつものように、それはユースケースに依存します。10ミリ秒ごとにクエリを実行する必要がある場合、はい、速度が遅すぎます。
profesor_falken

はい、私は勝利について話していました、Linuxでは「ps ... <options>」の使用を見つけたので、はるかに速くなると思います
Gobliins

よし、githubプロジェクトで問題を作成したい場合は、最終的に調べて、Winでのパフォーマンスを改善できるかどうかを確認します。実際、私はLinuxでそれを使用したので、実装に勝つためにあまり注意を払わなかった:-S
profesor_falken

それは結構ですが、私が探していたもの:プロセスのstartTimeで、私が間違っていない場合、指定された時間を1日(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とtasklistWindows を解析することが最善のオプションです。

Windowsの場合、参照できます:http : //www.rgagnon.com/javadetails/java-0593.html

Linuxの缶パイプの結果ps auxを通してgrep迅速かつ簡単に検索/処理するだろう、あまりにも、。窓にも似たようなものが見つかると思います。



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()、それ以外の場合は、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

これは、タスクを取得して名前を取得する関数の私のコードであり、リストからアクセスできるようにリストに追加することもできます。データを含む一時ファイルを作成し、ファイルを読み取って.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に組み込まれているタスクマネージャーを複製してみました。誰か興味があれば、そのデモをお送りします。
ディランウェドマン2018
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.