简体   繁体   English

Windows 8/10中活动窗口的进程名称

[英]Name of process for active window in Windows 8/10

The following sample has reliably returned the name of the process that is associated with the active window, but does not work with the newer modern/universal apps because it returns the name of a helper process WWAHost.exe on Windows 8 and ApplicationFrameHost.exe on Windows 10 rather than the name of the app. 以下示例已可靠地返回与活动窗口关联的进程的名称,但不适用于较新的现代/通用应用程序,因为它返回Windows 8上的帮助程序进程WWAHost.exeApplicationFrameHost.exe上的名称Windows 10而不是应用程序的名称。

HWND active_window = GetForegroundWindow();
GetWindowThreadProcessId(active_window, &active_process_id);
HANDLE active_process = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, active_process_id);
GetProcessImageFileName(active_process, image_name, 512);

With Windows 10 the ApplicationFrameHost.exe is the process that creates the window handles and is what gets returned by GetWindowThreadProcessId(), is there another Win32 API that can be used to get the active process of universal app that is active? 在Windows 10中,ApplicationFrameHost.exe是创建窗口句柄的过程,也是GetWindowThreadProcessId()返回的内容,是否有另一个Win32 API可用于获取活动的通用应用程序的活动进程?

Also tried using GetApplicationUserModelId() and GetPackageFullName() with no success as they return APPMODEL_ERROR_NO_APPLICATION and APPMODEL_ERROR_NO_PACKAGE respectively because the active_process handle is just the helper process and not the process of the active application. 还尝试使用GetApplicationUserModelId()和GetPackageFullName()没有成功,因为它们分别返回APPMODEL_ERROR_NO_APPLICATION和APPMODEL_ERROR_NO_PACKAGE,因为active_process句柄只是辅助进程而不是活动应用程序的进程。

Any other APIs to use to get the process name of a Modern/Universal application given the hwnd of the window, or otherwise figure out the process name of the universal app is active. 在给定窗口的hwnd的情况下,用于获取Modern / Universal应用程序的进程名称的任何其他API,或以其他方式确定通用应用程序的进程名称是活动的。

Thanks in advance! 提前致谢!

Be sure to use the Spy++ utility when you want to reverse-engineer something like this. 当你想对这样的东西进行逆向工程时,一定要使用Spy ++实用程序。 Included with Visual Studio, you need the 64-bit version in Common7\\Tools\\spyxx_amd64.exe. 包含在Visual Studio中,您需要Common7 \\ Tools \\ spyxx_amd64.exe中的64位版本。 Use Search > Find Window and drag the bullseye to a UWP app, like Weather. 使用搜索>查找窗口并将靶心拖动到UWP应用程序,如天气。

You'll see the window you'll find with GetForegroundWindow(), it has at least 3 child windows: 您将看到使用GetForegroundWindow()找到的窗口,它至少有3个子窗口:

  • ApplicationFrameTitleBarWindow ApplicationFrameTitleBarWindow
  • ApplicationFrameInputSinkWindow ApplicationFrameInputSinkWindow
  • Windows.Core.UI.CoreWindow, that's the host window for the UWP app and the one you are interested in. Right-click it and select Properties, Process tab, click the Process ID. Windows.Core.UI.CoreWindow,这是UWP应用程序的主机窗口和您感兴趣的应用程序。右键单击它并选择“属性”,“进程”选项卡,单击“进程ID”。 That takes you to the real owner process you want to know. 这会将您带到您想要了解的真实所有者流程。

So you just need to make an extra step from the code you already have, you just have to enumerate the child windows and look for one with a different owner process. 因此,您只需要从已有的代码中进行额外的步骤,您只需枚举子窗口并查找具有不同所有者进程的窗口。 Some C code, trying to make it as universal as possible without making too many assumptions and not enough error checking: 一些C代码,试图使其尽可能通用,而不会做太多的假设和错误检查:

#include <stdio.h>
#include <Windows.h>

typedef struct {
    DWORD ownerpid;
    DWORD childpid;
} windowinfo;

BOOL CALLBACK EnumChildWindowsCallback(HWND hWnd, LPARAM lp) {
    windowinfo* info = (windowinfo*)lp;
    DWORD pid = 0;
    GetWindowThreadProcessId(hWnd, &pid);
    if (pid != info->ownerpid) info->childpid = pid;
    return TRUE;
}

int main()
{
    Sleep(2000);
    HWND active_window = GetForegroundWindow();
    windowinfo info = { 0 };
    GetWindowThreadProcessId(active_window, &info.ownerpid);
    info.childpid = info.ownerpid;
    EnumChildWindows(active_window, EnumChildWindowsCallback, (LPARAM)&info);
    HANDLE active_process = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, info.childpid);
    WCHAR image_name[MAX_PATH] = { 0 };
    DWORD bufsize = MAX_PATH;
    QueryFullProcessImageName(active_process, 0, image_name, &bufsize);
    wprintf(L"%s\n", image_name);
    CloseHandle(active_process);
    return 0;
}

Output on the Weather program: 天气计划的输出:

C:\\Program Files\\WindowsApps\\Microsoft.BingWeather_4.5.168.0_x86__8wekyb3d8bbwe\\ Microsoft.Msn.Weather.exe C:\\ Program Files \\ WindowsApps \\ Microsoft.BingWeather_4.5.168.0_x86__8wekyb3d8bbwe \\ Microsoft.Msn.Weather.exe

Here is a small console app application that continuously (so you can test it easily selecting different windows on your desktop) display information about the current foreground window process and store process, if any. 这是一个小型控制台应用程序应用程序,连续(因此您可以轻松地在桌面上选择不同的窗口进行测试)显示有关当前前台窗口进程和存储过程的信息(如果有)。

Apps can have a window hierarchy that can span multiple processes. 应用可以具有可以跨越多个进程的窗口层次结构。 What I do here is search the first sub window that has the 'Windows.UI.Core.CoreWindow' class name. 我在这里做的是搜索具有'Windows.UI.Core.CoreWindow'类名的第一个子窗口。

This app uses the UIAutomation API (and also smart pointers, smart BSTRs and smart VARIANTs provided by the #import directive). 此应用程序使用UIAutomation API (以及#import指令提供的智能指针,智能BSTR和智能VARIANT)。 I suppose you can do the same with standard Windows SDK, but I find the UIAutomation used this way quite elegant. 我想你可以用标准的Windows SDK做同样的事情,但我发现UIAutomation使用这种方式非常优雅。

#include "stdafx.h"
#import "UIAutomationCore.dll"
using namespace UIAutomationClient;

int main()
{
    // initialize COM, needed for UIA
    CoInitialize(NULL);

    // initialize main UIA class
    IUIAutomationPtr pUIA(__uuidof(CUIAutomation));

    do
    {
        // get the Automation element for the foreground window
        IUIAutomationElementPtr foregroundWindow = pUIA->ElementFromHandle(GetForegroundWindow());
        wprintf(L"pid:%i\n", foregroundWindow->CurrentProcessId);

        // prepare a [class name = 'Windows.UI.Core.CoreWindow'] condition
        _variant_t prop = L"Windows.UI.Core.CoreWindow";
        IUIAutomationConditionPtr condition = pUIA->CreatePropertyCondition(UIA_ClassNamePropertyId, prop);

        // get the first element (window hopefully) that satisfies this condition
        IUIAutomationElementPtr coreWindow = foregroundWindow->FindFirst(TreeScope::TreeScope_Children, condition);
        if (coreWindow)
        {
            // get the process id property for that window
            wprintf(L"store pid:%i\n", coreWindow->CurrentProcessId);
        }

        Sleep(1000);
    } while (TRUE);

cleanup:
    CoUninitialize();
    return 0;
}

Does taking snapshot of running processes and pulling the name out of it by comparing process id not work? 是否通过比较进程ID来获取正在运行的进程的快照并从中提取名称? Full reference here: 完整参考:

https://msdn.microsoft.com/en-us/library/windows/desktop/ms686837(v=vs.85).aspx https://msdn.microsoft.com/en-us/library/windows/desktop/ms686837(v=vs.85).aspx

But you fix the snapshot with CreateToolhelp32Snapshot(). 但是您使用CreateToolhelp32Snapshot()修复了快照。

Or from WTSEnumerateProcesses() and surrounding API? 或者来自WTSEnumerateProcesses()和周围的API?

Pretty sure it worked in Win 8. Is it broken in 10? 很确定它在Win 8中有效。它在10中被打破了吗?

Starting from Win10 Anniversary Update ApplicationFrameHost child window return anything but UWP application. 从Win10周年更新开始ApplicationFrameHost子窗口返回除UWP应用程序之外的任何内容。 It worked only in Tablet mode after relogon. 在relogon之后,它仅在平板电脑模式下工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM