如何用Java获取Windows任务管理器中显示的当前运行应用名称?
Java获取Windows任务管理器中显示的应用名称问题
我希望用Java获取Windows任务管理器中显示的当前运行应用名称(如IntelliJ IDEA、Google Chrome),但现有代码无法实现预期效果。
现有代码
import com.sun.jna.Native; import com.sun.jna.platform.win32.*; import com.sun.jna.ptr.IntByReference; public class AppList { public static void main(String[] args) { // 打印活动窗口标题(不符合需求) User32 user32 = User32.INSTANCE; WinDef.HWND hwnd = user32.GetForegroundWindow(); char[] title = new char[1024]; user32.GetWindowText(hwnd, title, title.length); System.out.println("Active window: " + String.valueOf(title)); // 输出:"Active window: Project4 - AppList.java" // 打印活动应用路径并格式化(仍不符合需求) IntByReference processId = new IntByReference(); int id = user32.GetWindowThreadProcessId(hwnd, processId); WinNT.HANDLE processHandle = Kernel32.INSTANCE.OpenProcess( WinNT.PROCESS_QUERY_INFORMATION | WinNT.PROCESS_VM_READ, false, processId.getValue()); char[] exePath = new char[1024]; Psapi.INSTANCE.GetModuleFileNameExW(processHandle, null, exePath, exePath.length); String exePathStr = Native.toString(exePath); System.out.println(exePathStr); // 输出:"C:\Program Files\JetBrains\IntelliJ IDEA Community Edition 2023.3.2\bin\idea64.exe" // 格式化处理 String activeAppName = exePathStr.substring(exePathStr.lastIndexOf("\\") + 1) .replace(".exe", "").toLowerCase(); char firstChar = Character.toUpperCase(activeAppName.charAt(0)); activeAppName = firstChar + activeAppName.substring(1); System.out.println(activeAppName); Kernel32.INSTANCE.CloseHandle(processHandle); // 得到"Idea64"而非"IntelliJ IDEA" // 得到"Chrome"而非"Google Chrome" // 得到"Applicationframehost"而非"设置" // 任务管理器相关完全无法正常工作 } }
现有代码的问题
- 第一种方法获取活动窗口标题,仅部分场景可用,多数情况不符合需求;
- 第二种方法获取应用路径并格式化,仅部分场景(如Spotify)可用,多数情况得到奇怪名称或完全失效。
我已花费数小时搜索和咨询AI,仅找到这两种方法,未能解决问题。
解决方案
核心思路
任务管理器显示的名称来源分两类:
- 传统Win32应用:名称来自可执行文件的文件描述(对应文件属性“详细信息”中的描述)
- UWP应用(如“设置”、应用商店应用):名称来自应用包的显示名称
修正后的代码
import com.sun.jna.Native; import com.sun.jna.platform.win32.*; import com.sun.jna.ptr.IntByReference; import com.sun.jna.win32.W32APIOptions; public class TaskManagerAppName { public interface Shell32 extends com.sun.jna.platform.win32.Shell32 { Shell32 INSTANCE = Native.load("shell32", Shell32.class, W32APIOptions.DEFAULT_OPTIONS); int SHGetFileInfoW(WinDef.LPCWSTR pszPath, int dwFileAttributes, SHFILEINFOW psfi, int cbFileInfo, int uFlags); } public static void main(String[] args) { User32 user32 = User32.INSTANCE; WinDef.HWND hwnd = user32.GetForegroundWindow(); IntByReference processId = new IntByReference(); user32.GetWindowThreadProcessId(hwnd, processId); int pid = processId.getValue(); // 打开进程获取可执行文件路径 WinNT.HANDLE processHandle = Kernel32.INSTANCE.OpenProcess( WinNT.PROCESS_QUERY_INFORMATION | WinNT.PROCESS_VM_READ, false, pid); char[] exePath = new char[1024]; Psapi.INSTANCE.GetModuleFileNameExW(processHandle, null, exePath, exePath.length); String exePathStr = Native.toString(exePath); Kernel32.INSTANCE.CloseHandle(processHandle); // 获取Win32应用的显示名称(任务管理器显示的名称) Shell32.SHFILEINFOW shfi = new Shell32.SHFILEINFOW(); int result = Shell32.INSTANCE.SHGetFileInfoW(new WinDef.LPCWSTR(exePathStr), 0, shfi, shfi.size(), Shell32.SHGFI_DISPLAYNAME | Shell32.SHGFI_USEFILEATTRIBUTES); String appName; if (result != 0) { appName = Native.toString(shfi.szDisplayName); } else { // 处理UWP应用,通过PowerShell获取包显示名称 appName = getUwpAppName(pid); if (appName == null) { // 降级到exe名称作为备选 appName = exePathStr.substring(exePathStr.lastIndexOf("\\") + 1).replace(".exe", ""); } } System.out.println("任务管理器显示名称: " + appName); } // 获取UWP应用的显示名称 private static String getUwpAppName(int pid) { try { // 调用PowerShell命令查询UWP应用包信息 Process process = Runtime.getRuntime().exec( "powershell -Command \"Get-Process -Id " + pid + " | Select-Object -ExpandProperty Path | Get-AppxPackage -PackageTypeFilter Main | Select-Object -ExpandProperty DisplayName\""); process.waitFor(); String output = new String(process.getInputStream().readAllBytes()).trim(); return output.isEmpty() ? null : output; } catch (Exception e) { return null; } } }
代码说明
- SHGetFileInfoW:系统API,直接读取可执行文件的显示名称,完美匹配任务管理器中Win32应用的名称(如
idea64.exe对应IntelliJ IDEA) - UWP应用处理:通过PowerShell调用系统命令,获取UWP应用的包显示名称,解决“设置”这类应用显示为
Applicationframehost的问题 - 降级逻辑:当以上方法失效时,自动回退到exe名称,保证基础可用性
内容的提问来源于stack exchange,提问作者Mat
相关产品推荐
相关产品推荐

