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

如何获取EnumWindows() API未枚举到的Windows系统窗口?

解决EnumWindows无法枚举系统特殊可见窗口的方案

EnumWindows会漏掉开始菜单、Game Bar、闹钟面板这类用户可见的系统/特殊窗口,原因是它们要么属于UWP沉浸式窗口,要么是系统保护的窗口对象。以下是几种经过验证的处理方案:

1. 遍历完整窗口链(替代EnumWindows)

EnumWindows是高层封装,会过滤掉部分系统窗口。改用从桌面窗口开始,通过GetWindow递归遍历所有子窗口和同级窗口的方式,能抓到更多窗口:

#include <windows.h>
#include <wchar.h>

BOOL CALLBACK EnumAllWindowsProc(HWND hwnd, LPARAM lParam) {
    // 过滤不可见窗口
    if (!IsWindowVisible(hwnd)) {
        return TRUE;
    }
    // 获取窗口标题和类名
    WCHAR szTitle[256] = {0};
    GetWindowTextW(hwnd, szTitle, 256);
    WCHAR szClass[256] = {0};
    GetClassNameW(hwnd, szClass, 256);
    // 输出信息(可替换为自定义处理逻辑)
    wprintf(L"窗口标题:%ls | 窗口类名:%ls\n", szTitle, szClass);
    return TRUE;
}

void EnumAllWindows() {
    HWND hDesktop = GetDesktopWindow();
    // 遍历桌面的直接子窗口
    HWND hWnd = GetWindow(hDesktop, GW_CHILD);
    while (hWnd != NULL) {
        EnumAllWindowsProc(hWnd, 0);
        // 递归遍历当前窗口的所有子窗口
        EnumChildWindows(hWnd, EnumAllWindowsProc, 0);
        // 切换到下一个同级窗口
        hWnd = GetWindow(hWnd, GW_HWNDNEXT);
    }
}

这种方式不会跳过系统级窗口,需要自己过滤无效窗口(比如无标题、不可见的)。

2. 启用UI Access权限(已验证有效)

你之前测试的带UI_ACCESS属性的工具能枚举这些窗口,是因为该权限允许程序访问受保护的系统窗口。给程序添加该权限的步骤:

  • 在程序的manifest文件中添加配置:<requestedExecutionLevel level="requireAdministrator" uiAccess="true" />
  • 将程序放在受信任目录(如C:\Program Files或C:\Program Files (x86))
  • 给程序签名(测试时可用自签名证书)
    注意:UI Access权限需要管理员权限,且程序路径必须安全,否则系统会阻止运行。

3. 针对UWP/沉浸式窗口的枚举(Windows 10+)

开始菜单、Game Bar这类属于UWP应用窗口,Win32 API默认无法直接枚举,可使用WinRT API获取这些窗口信息:

C# 示例

using Windows.UI.WindowManagement;
using System.Diagnostics;

async void EnumUwpWindows() {
    var allAppWindows = await AppWindow.GetAllAsync();
    foreach (var window in allAppWindows) {
        Debug.WriteLine($"UWP窗口标题:{window.Title} | 窗口ID:{window.Id}");
    }
}

C++/WinRT 示例

#include <winrt/Windows.UI.WindowManagement.h>
#include <winrt/Windows.Foundation.h>
#include <iostream>

using namespace winrt;
using namespace Windows::UI::WindowManagement;
using namespace Windows::Foundation;

IAsyncAction EnumUwpWindows() {
    auto appWindows = co_await AppWindow::GetAllAsync();
    for (auto const& window : appWindows) {
        std::wcout << L"UWP窗口标题:" << window.Title().c_str() << L"\n";
    }
}

4. 利用进程诊断API获取窗口(Windows 10+)

通过Windows.System.Diagnostics.ProcessDiagnosticInfo可以枚举所有进程,再获取每个进程关联的窗口信息,包括UWP进程:

using Windows.System.Diagnostics;
using System.Diagnostics;

void EnumProcessWindows() {
    foreach (var processInfo in ProcessDiagnosticInfo.GetForProcesses()) {
        foreach (var windowInfo in processInfo.WindowDiagnosticInfos) {
            Debug.WriteLine($"窗口标题:{windowInfo.Title} | 进程ID:{processInfo.ProcessId}");
        }
    }
}

这种方式能覆盖所有进程关联的窗口,包括被EnumWindows漏掉的系统窗口。

额外提示

  • 部分特殊窗口有固定类名,比如开始菜单的XamlExplorerHostWindow、Game Bar的ApplicationFrameWindow,可通过GetClassName识别并针对性处理。
  • 若系统启用了多虚拟桌面,需先用EnumDesktops枚举所有桌面,再在每个桌面上调用EnumDesktopWindows枚举窗口。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 08:28:36