Подтвердить что ты не робот

Название процесса для активного окна в Windows 8/10

Следующий пример надежно возвращает имя процесса, связанного с активным окном, но не работает с новыми современными/универсальными приложениями, поскольку возвращает имя вспомогательного процесса WWAHost.exe в Windows 8 и ApplicationFrameHost.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);

В Windows 10 ApplicationFrameHost.exe - это процесс, который создает дескрипторы окон, и это то, что возвращается GetWindowThreadProcessId(), есть ли еще один API Win32, который можно использовать для активного активного активного универсального приложения?

Также не удалось успешно использовать GetApplicationUserModelId() и GetPackageFullName(), поскольку они возвращают APPMODEL_ERROR_NO_APPLICATION и APPMODEL_ERROR_NO_PACKAGE соответственно, потому что дескриптор active_process - это всего лишь вспомогательный процесс, а не процесс активного приложения.

Любые другие API-интерфейсы, которые будут использоваться для получения имени процесса для нового/универсального приложения с учетом hwnd окна, или каким-либо иным образом определить, что имя процесса универсального приложения активно.

Спасибо заранее!

4b9b3361

Ответ 1

Обязательно используйте служебную программу Spy ++, если хотите перепрограммировать что-то вроде этого. В комплекте с Visual Studio вам понадобится 64-разрядная версия в Common7\Tools\spyxx_amd64.exe. Используйте Search > Find Window и перетащите bullseye в приложение UWP, например Weather.

Вы увидите окно, которое вы найдете с помощью GetForegroundWindow(), оно имеет как минимум 3 дочерних окна:

  • ApplicationFrameTitleBarWindow
  • ApplicationFrameInputSinkWindow
  • Windows.Core.UI.CoreWindow, это окно хоста для приложения UWP и того, которое вас интересует. Щелкните его правой кнопкой мыши и выберите вкладку "Свойства", "Процесс", щелкните "Идентификатор процесса". Это приведет вас к реальному процессу владельца, который вы хотите знать.

Итак, вам просто нужно сделать дополнительный шаг от кода, который у вас уже есть, вам просто нужно перечислить дочерние окна и искать один с другим процессом владельца. Некоторый 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;
}

Результат в программе Weather:

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

Ответ 2

Вот небольшое приложение для консольных приложений, которое постоянно (так что вы можете легко протестировать его, выбрав различные окна на рабочем столе). Отобразите информацию о текущем процессе окна переднего плана и сохраните процесс, если он есть.

Приложения могут иметь иерархию окон, которая может охватывать несколько процессов. Что я здесь делаю, это поиск в первом вспомогательном окне с именем класса "Windows.UI.Core.CoreWindow".

Это приложение использует API UIAutomation (а также интеллектуальные указатели, интеллектуальные BSTR и интеллектуальные VARIANT, предоставленные директивой #import). Я полагаю, вы можете сделать то же самое со стандартным SDK Windows, но я нахожу, что 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;
}

Ответ 3

Делает ли снимок запущенных процессов и вытягивает имя из него, сравнивая идентификатор процесса, не работает? Полное упоминание здесь:

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

Но вы устанавливаете моментальный снимок с помощью CreateToolhelp32Snapshot().

Или из WTSEnumerateProcesses() и окружающего API?

Довольно уверен, что это сработало в Win 8. Разве это сломано в 10?

Ответ 4

Начиная с Win10 Anniversary Update. Окно дочернего окна ApplicationFrameHost возвращает ничего, кроме приложения UWP. Он работал только в режиме Tablet после relogon.