You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Java获取仅包含当前已打开程序的列表(排除后台进程)

获取Windows上已打开的可见程序列表(Java实现)

嗨,我懂你要的是用户能看到的已打开程序(带可见窗口的),而不是tasklist.exe返回的所有后台进程——之前的代码确实会把系统服务、后台守护进程这类进程都列出来,完全不符合需求。下面给你两个实用的解决方案:

方案1:用PowerShell命令过滤(快速实现)

Windows的PowerShell可以直接筛选出有主窗口标题的进程,这正是我们要的“已打开程序”。Java里可以调用PowerShell命令来实现:

import java.io.BufferedReader;
import java.io.InputStreamReader;

public class OpenProgramsList {
    public static void main(String[] args) {
        try {
            // 调用PowerShell,筛选有主窗口标题的进程,并格式化输出
            Process p = Runtime.getRuntime().exec(new String[]{
                "powershell.exe",
                "-Command",
                "Get-Process | Where-Object {$_.MainWindowTitle -ne \"\"} | Select-Object Name, MainWindowTitle, Id | Format-Table -AutoSize"
            });

            // 注意指定UTF-8编码,避免中文窗口标题乱码
            BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream(), "UTF-8"));
            String line;
            while ((line = input.readLine()) != null) {
                // 跳过空行,让输出更整洁
                if (!line.trim().isEmpty()) {
                    System.out.println(line);
                }
            }
            input.close();
            p.waitFor();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

说明:

  • 这个命令会过滤掉MainWindowTitle为空的进程(也就是没有可见窗口的后台进程)
  • 返回的信息包括进程名、窗口标题、进程ID,格式清晰易读
  • 一定要指定UTF-8编码,否则中文窗口标题会出现乱码问题

方案2:用JNA调用Windows API(精准控制)

如果不想依赖PowerShell,或者需要更精细的窗口筛选逻辑(比如排除最小化窗口),可以用JNA直接调用Windows的User32和Kernel32 API,枚举所有可见顶层窗口并获取对应的进程信息:

第一步:引入JNA依赖(Maven)

<dependency>
    <groupId>net.java.dev.jna</groupId>
    <artifactId>jna</artifactId>
    <version>5.13.0</version>
</dependency>
<dependency>
    <groupId>net.java.dev.jna</groupId>
    <artifactId>jna-platform</artifactId>
    <version>5.13.0</version>
</dependency>

第二步:实现代码

import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.platform.win32.User32;
import com.sun.jna.platform.win32.WinDef;
import com.sun.jna.platform.win32.WinNT;
import com.sun.jna.ptr.IntByReference;

import java.util.HashSet;
import java.util.Set;

public class VisibleAppsLister {
    public static void main(String[] args) {
        Set<String> visibleApps = getVisibleApplications();
        System.out.println("已打开的可见程序:");
        for (String app : visibleApps) {
            System.out.println("- " + app);
        }
    }

    private static Set<String> getVisibleApplications() {
        Set<String> appNames = new HashSet<>();
        User32 user32 = User32.INSTANCE;

        // 枚举所有顶层窗口
        user32.EnumWindows((hWnd, data) -> {
            // 只保留可见且有窗口标题的窗口
            if (user32.IsWindowVisible(hWnd) && user32.GetWindowTextLength(hWnd) > 0) {
                IntByReference pid = new IntByReference();
                // 获取窗口对应的进程ID
                user32.GetWindowThreadProcessId(hWnd, pid);
                // 打开进程以获取进程名
                WinNT.HANDLE hProcess = Kernel32.INSTANCE.OpenProcess(
                        WinNT.PROCESS_QUERY_INFORMATION | WinNT.PROCESS_VM_READ,
                        false,
                        pid.getValue()
                );
                if (hProcess != null) {
                    char[] buffer = new char[1024];
                    Kernel32.INSTANCE.GetModuleBaseName(hProcess, null, buffer, buffer.length);
                    String appName = Native.toString(buffer);
                    if (!appName.isEmpty()) {
                        appNames.add(appName);
                    }
                    // 记得关闭进程句柄,避免资源泄漏
                    Kernel32.INSTANCE.CloseHandle(hProcess);
                }
            }
            return true; // 继续枚举下一个窗口
        }, null);

        return appNames;
    }

    // 自定义Kernel32接口,补充需要的方法
    public interface Kernel32 extends com.sun.jna.platform.win32.Kernel32 {
        Kernel32 INSTANCE = Native.load("kernel32", Kernel32.class);

        WinNT.HANDLE OpenProcess(int dwDesiredAccess, boolean bInheritHandle, int dwProcessId);

        int GetModuleBaseName(WinNT.HANDLE hProcess, Pointer hModule, char[] lpBaseName, int nSize);
    }
}

说明:

  • 这个方法直接和Windows系统交互,结果更精准,能捕获所有可见窗口对应的程序
  • 你可以修改判断条件,比如加上user32.IsIconic(hWnd) == false来排除最小化的窗口
  • 注意要关闭进程句柄,避免系统资源泄漏

内容的提问来源于stack exchange,提问作者Parzavil

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 08:07:46