Name of process for active window in Windows 8/10

前端 未结 4 1033
南方客
南方客 2020-12-02 15:06

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

相关标签:
4条回答
  • 2020-12-02 15:10

    Be sure to use the Spy++ utility when you want to reverse-engineer something like this. Included with Visual Studio, you need the 64-bit version in Common7\Tools\spyxx_amd64.exe. Use Search > Find Window and drag the bullseye to a UWP app, like Weather.

    You'll see the window you'll find with GetForegroundWindow(), it has at least 3 child windows:

    • ApplicationFrameTitleBarWindow
    • 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. 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:

    #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

    0 讨论(0)
  • 2020-12-02 15:15

    Does taking snapshot of running processes and pulling the name out of it by comparing process id not work? Full reference here:

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

    But you fix the snapshot with CreateToolhelp32Snapshot().

    Or from WTSEnumerateProcesses() and surrounding API?

    Pretty sure it worked in Win 8. Is it broken in 10?

    0 讨论(0)
  • 2020-12-02 15:32

    Starting from Win10 Anniversary Update ApplicationFrameHost child window return anything but UWP application. It worked only in Tablet mode after relogon.

    0 讨论(0)
  • 2020-12-02 15:35

    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.

    This app uses the UIAutomation API (and also smart pointers, smart BSTRs and smart VARIANTs provided by the #import directive). I suppose you can do the same with standard Windows SDK, but I find the UIAutomation used this way quite elegant.

    #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;
    }
    
    0 讨论(0)
提交回复
热议问题