Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

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?

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.

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.

Thanks in advance!

like image 870
Tim Beaudet Avatar asked Sep 02 '15 18:09

Tim Beaudet


People also ask

What is active Windows computer?

active windows. DEFINITIONS1. an area on a computer screen showing the program that you are using at a particular time. Synonyms and related words. On the computer screen.

How do I end a task in Windows 8?

Terminate using Task Manager Press Ctrl + Alt + Del on your keyboard to bring up the Windows logon screen. Select Task Manager. Under the Processes tab, locate the app you'd like to close. Right-click the app and select End Task from the drop-down menu that appears.


3 Answers

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

like image 175
Hans Passant Avatar answered Oct 17 '22 19:10

Hans Passant


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;
}
like image 38
Simon Mourier Avatar answered Oct 17 '22 20:10

Simon Mourier


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?

like image 2
Dmitry Rubanovich Avatar answered Oct 17 '22 19:10

Dmitry Rubanovich