Windows系统中如何获取应用名称及关联进程?求代码示例
在Windows中获取应用名称及对应进程的实现方案
Windows任务管理器中的“应用名称”通常对应进程的窗口标题、应用程序产品名称(从可执行文件版本信息读取),或是UWP应用的包名称。以下是PowerShell、Python、Java的实现示例,实现类似任务管理器的应用-进程关联展示:
一、PowerShell实现
结合Get-Process与WMI/CIM获取进程详细信息,同时对同一应用的进程进行分组:
1. 桌面应用(含窗口)+ 进程分组
# 获取所有进程,补充产品名称和窗口标题 $processes = Get-Process | ForEach-Object { $exePath = $_.Path $productName = $null if ($exePath) { # 从可执行文件版本信息获取产品名称 $versionInfo = (Get-Item $exePath).VersionInfo $productName = $versionInfo.ProductName } [PSCustomObject]@{ PID = $_.Id ProcessName = $_.Name AppName = if ($productName) { $productName } else { if ($_.MainWindowTitle -eq "") { "后台进程" } else { $_.MainWindowTitle } } ExePath = $exePath } } # 按应用名称分组展示 $processes | Group-Object -Property AppName | ForEach-Object { Write-Host "=== 应用名称: $($_.Name) ===" $_.Group | Select-Object PID, ProcessName, ExePath | Format-Table -AutoSize }
2. 包含UWP应用的扩展版本
# 获取UWP应用的包信息与进程关联 $uwpProcesses = Get-CimInstance Win32_Process | Where-Object { $_.ExecutablePath -like "*\WindowsApps\*" } | ForEach-Object { $packageFolder = Split-Path $_.ExecutablePath -Parent $packageName = ($packageFolder -split "\\")[ -2 ] $appName = (Get-AppxPackage -Name $packageName).DisplayName [PSCustomObject]@{ PID = $_.ProcessId ProcessName = $_.Name AppName = if ($appName) { $appName } else { $packageName } ExePath = $_.ExecutablePath } } # 合并桌面应用与UWP应用并分组展示 ($processes + $uwpProcesses) | Group-Object -Property AppName | ForEach-Object { Write-Host "=== 应用名称: $($_.Name) ===" $_.Group | Select-Object PID, ProcessName, ExePath | Format-Table -AutoSize }
二、Python实现
使用psutil获取进程基础信息,结合pywin32读取可执行文件的版本信息来获取应用名称,实现进程分组:
1. 依赖安装
pip install psutil pywin32
2. 代码实现
import psutil import win32api from collections import defaultdict def get_app_name(exe_path): """从可执行文件路径获取应用产品名称""" try: # 获取文件版本信息 file_version_info = win32api.GetFileVersionInfo(exe_path, "\\") # 提取产品名称 lang, codepage = win32api.GetFileVersionInfo(exe_path, "\\VarFileInfo\\Translation")[0] str_info_path = f"\\StringFileInfo\\{lang:04x}{codepage:04x}\\ProductName" return file_version_info[str_info_path] except Exception: return None # 按应用名称分组存储进程 app_process_map = defaultdict(list) for proc in psutil.process_iter(['pid', 'name', 'exe', 'main_window_title']): try: proc_info = proc.info exe_path = proc_info['exe'] app_name = get_app_name(exe_path) # 优先级:产品名称 > 主窗口标题 > 进程名称 if not app_name: app_name = proc_info['main_window_title'] if proc_info['main_window_title'] else proc_info['name'] # 添加到对应应用分组 app_process_map[app_name].append({ 'pid': proc_info['pid'], 'process_name': proc_info['name'], 'window_title': proc_info['main_window_title'] }) except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess): continue # 打印结果 for app_name, processes in app_process_map.items(): print(f"=== 应用名称: {app_name} ===") for proc in processes: print(f"PID: {proc['pid']}, 进程名: {proc['process_name']}, 窗口标题: {proc['window_title']}") print("-" * 50)
三、Java实现
通过JNA调用Windows原生API获取进程的可执行文件路径,再读取文件版本信息中的产品名称,实现应用-进程关联:
1. 依赖(Maven)
<dependencies> <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> </dependencies>
2. 代码实现
import com.sun.jna.Pointer; import com.sun.jna.platform.win32.*; import com.sun.jna.ptr.IntByReference; import java.io.File; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.ArrayList; public class WindowsAppProcessLister { // 获取进程的可执行文件路径 private static String getProcessExePath(int pid) { WinNT.HANDLE processHandle = Kernel32.INSTANCE.OpenProcess( WinNT.PROCESS_QUERY_INFORMATION | WinNT.PROCESS_VM_READ, false, pid); if (processHandle == null || processHandle.equals(WinNT.HANDLE.INVALID_HANDLE_VALUE)) { return null; } char[] exePath = new char[WinDef.MAX_PATH]; Psapi.INSTANCE.GetModuleFileNameExW(processHandle, null, exePath, exePath.length); Kernel32.INSTANCE.CloseHandle(processHandle); return Native.toString(exePath).trim(); } // 从文件路径获取应用产品名称 private static String getAppProductName(String exePath) { if (exePath == null || exePath.isEmpty()) return null; File file = new File(exePath); if (!file.exists()) return null; try { VersionInfo versionInfo = VersionInfo.getVersionInfo(file.getAbsolutePath()); return versionInfo.getProductName(); } catch (Exception e) { return null; } } public static void main(String[] args) { Map<String, List<ProcessInfo>> appProcessMap = new HashMap<>(); // 枚举所有进程ID IntByReference processCount = new IntByReference(); int[] processIds = new int[1024]; if (!Psapi.INSTANCE.EnumProcesses(processIds, processIds.length * 4, processCount)) { System.err.println("枚举进程失败"); return; } int count = processCount.getValue() / 4; for (int i = 0; i < count; i++) { int pid = processIds[i]; if (pid == 0) continue; String exePath = getProcessExePath(pid); String appName = getAppProductName(exePath); if (appName == null) { appName = exePath != null ? new File(exePath).getName() : "未知进程"; } ProcessInfo info = new ProcessInfo(pid, exePath); appProcessMap.computeIfAbsent(appName, k -> new ArrayList<>()).add(info); } // 打印结果 for (Map.Entry<String, List<ProcessInfo>> entry : appProcessMap.entrySet()) { System.out.println("=== 应用名称: " + entry.getKey() + " ==="); for (ProcessInfo info : entry.getValue()) { System.out.printf("PID: %d, 可执行路径: %s%n", info.pid, info.exePath); } System.out.println("--------------------------------------------------"); } } static class ProcessInfo { int pid; String exePath; public ProcessInfo(int pid, String exePath) { this.pid = pid; this.exePath = exePath; } } }
内容的提问来源于stack exchange,提问作者JJG
相关产品推荐
相关产品推荐

