如何检查Windows上的进程是否正在运行?

4
我正在尝试编写一个程序,以了解进程是否在Windows上活动,并在Java中使用它。我在互联网上找到了两种不同的解决方案:
- 选项1 - 选项2 但这完全不是我要寻找的。
根据选项1,我想要一种方法来引用该进程(并检测它是否处于活动/运行状态),但不需要在整个tasklist中进行搜索然后再搜索它。我在寻找是否有一种直接的方法来实现这一点。
我还考虑添加一个过滤器到tasklist中,但找不到任何仅获取我要查找的进程的过滤器。我在我的命令行上使用“tasklist /?”看到了所有选项。
然后我搜索了第二个选项和wmic(我以前从未听说过),似乎wmic允许您在命令行上执行任务(如果我错了请纠正我)。
所以,我有两个问题
  • 是否有直接的方法在Windows中使用Java知道进程是否处于活动状态?尝试避免在完整的任务列表中搜索或使用wmic

  • 如果不可能,那么上面提到的两个选项中哪一个在编写高效程序方面更好?

提前感谢!

您可以使用Java Native来导入Process32Next()函数以枚举进程。例如:http://stackoverflow.com/q/9877993/1207195 - Adriano Repetti
1
听起来你在设计一个完全虚假的系统。你真正想要解决什么问题? - IInspectable
4个回答

10
没有直接的方法来查询一般进程,因为每个操作系统处理它们的方式都不同。
你只能使用代理,例如直接使用操作系统命令...
但是,你可以使用带有/fi参数的tasklist.exe来查找特定进程。
例如:tasklist.exe /nh /fi "Imagename eq chrome.exe"
请注意必须使用双引号。
语法和用法在MS Technet site上可用。
相同的示例,在Java中过滤"chrome.exe":
String findProcess = "chrome.exe";
String filenameFilter = "/nh /fi \"Imagename eq "+findProcess+"\"";
String tasksCmd = System.getenv("windir") +"/system32/tasklist.exe "+filenameFilter;

Process p = Runtime.getRuntime().exec(tasksCmd);
BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));

ArrayList<String> procs = new ArrayList<String>();
String line = null;
while ((line = input.readLine()) != null) 
    procs.add(line);

input.close();

Boolean processFound = procs.stream().filter(row -> row.indexOf(findProcess) > -1).count() > 0;
// Head-up! If no processes were found - we still get: 
// "INFO: No tasks are running which match the specified criteria."

谢谢您的回答。我现在要尝试您的代码,但是我有一些问题。您是否使用ArrayList是因为BufferedReader也返回PID、控制台名称等信息?另外,当您执行Runtime.getRuntime().exec(tasksCmd);时,如果已经有进程在运行,它会创建一个新的进程吗?再次感谢! - Francisco Romero
有了你的代码,我终于搞定了,但我还有一个问题。你代码最后一行的目的是什么?:Boolean processFound = procs... 如果我省略它,代码可以工作,但如果我加上它,我的代码会抛出异常,所以我认为它是不必要的。是吗? - Francisco Romero
这只适用于Java8。您可以使用标准的for循环来查找所需的文本并进行替换。 - Leet-Falcon
最后一行的目的是检查我们没有收到“INFO:No tasks are running which match the specified criteria.”(在这种情况下,数组具有一些内容,但不是所需的进程)。 - Leet-Falcon
抛出异常和放置 throws Exception 是一样的吗? - Francisco Romero
@Error404 - 加入http://chat.stackoverflow.com/rooms/102426/how-to-check-if-a-process-is-running-on-windows,以便我们可以检查您面临的问题。 - Leet-Falcon

2

使用Java 9,您可以这样做:

Optional<ProcessHandle> processHandle = ProcessHandle.of(pid);
boolean isrunning = processHandle.isPresent() && processHandle.get().isAlive();

现在您也可以直接使用Java获取有关进程的一些信息。

Optional<ProcessHandle> processHandle = ProcessHandle.of(pid);
if(processHandle.isPresent()) {
 ProcessHandle.Info processInfo = processHandle.get().info();
 System.out.println("COMMAND: " + processInfo.command().orElse(""));
 System.out.println("CLI: " + processInfo.commandLine().orElse(""));
 System.out.println("USER: " + processInfo.user().orElse(""));
 System.out.println("START TIME: " + processInfo.startInstant().orElse(null));
 System.out.println("TOTAL CPU: " + processInfo.totalCpuDuration().orElse(null));

}

1
你从哪里获取PID?如果你有PID,那么你已经知道该进程正在运行。 - tomsv
“isPresent()”和“get().isAlive()”有什么区别?我认为“isPresent()”已经足够了,因为它在进程未运行时也会返回false。你有什么想法吗? - Nur1

0

最好的方法是从java实例启动进程。这种方法的优点是您可以完全确定运行的进程是您启动的进程。使用tasklist,普通用户可以使用目标名称启动进程或在程序关闭后重用pid。

有关如何启动进程的信息,请参见this问题。

Process myProcess = Runtime.getRuntime().exec(command);

然后,您可以使用 Process 的方法来监视程序的状态,例如 myProcess.exitValue() 会阻塞直到程序关闭。


是的,这正是我正在寻找的,但我想在不执行进程的情况下尝试完成它。我知道我有一个活动进程,并希望将其存储在“Process”变量中,就像您在示例中所做的那样。有没有办法这样做,但是不从任务列表中获取所有进程数组? - Francisco Romero
如果该进程启动另一个进程并关闭另一个进程,则无法确定它是否仍在运行。这种方法是有缺陷的。 - nullsector76

0
你可以很容易地使用Java 9来实现这种方法。
public boolean isProcessRunning(String processName)
{
    return ProcessHandle
        .allProcesses()
        .filter(p -> p.info().command().isPresent())
        .anyMatch(n -> n.info().command().orElse("").endsWith(processName));
}

注意:我使用了endsWith(..),因为该命令包含了执行文件的完整路径。顺便说一下,如果你有进程ID,可以查看接受的答案。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接