2015-09-02 13 views
20

Il seguente esempio ha restituito in modo affidabile il nome del processo associato alla finestra attiva, ma non funziona con le nuove app moderne/universali perché restituisce il nome di un processo di supporto WWAHost.exe su Windows 8 e ApplicationFrameHost.exe su Windows 10 anziché il nome dell'app.Nome del processo per la finestra attiva in Windows 8/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); 

Con Windows 10 l'ApplicationFrameHost.exe è il processo che crea le maniglie delle finestre ed è ciò che viene restituito da GetWindowThreadProcessId(), c'è un altro API Win32 che può essere utilizzato per ottenere il processo attivo di applicazione universale che è attivo?

provato anche utilizzando GetApplicationUserModelId() e GetPackageFullName() senza successo come tornano APPMODEL_ERROR_NO_APPLICATION e APPMODEL_ERROR_NO_PACKAGE rispettivamente perché l'handle active_process è solo il processo di supporto e non il processo dell'applicazione attiva.

Qualsiasi altra API da utilizzare per ottenere il nome del processo di un'applicazione moderna/universale data la finestra della finestra, o altrimenti capire il nome del processo dell'app universale è attiva.

Grazie in anticipo!

+0

Hai provato ['QueryFullProcessImageName'] (https://msdn.microsoft.com/en-us/library/windows/desktop/ms684919%28v=vs.85%29.aspx)? – theB

+0

Sì e restituisce ancora un percorso a ApplicationFrameHost.exe, poiché il processo_handle restituito è il processo di supporto che ha creato la finestra. –

risposta

16

Assicurarsi di utilizzare l'utilità Spy ++ quando si desidera eseguire il reverse-engineering di questo tipo. Incluso in Visual Studio, è necessaria la versione a 64 bit in Common7 \ Tools \ spyxx_amd64.exe. Usa Cerca> Trova finestra e trascina il bullseye su un'app UWP, ad esempio Meteo.

Vedrete la finestra troverete con GetForegroundWindow(), ha almeno 3 finestre figlio:

  • ApplicationFrameTitleBarWindow
  • ApplicationFrameInputSinkWindow
  • Windows.Core.UI.CoreWindow, questa è la finestra host per l'app UWP e quella a cui sei interessato. Fai clic con il pulsante destro del mouse e seleziona Proprietà, scheda Processi, fai clic su Process ID. Questo ti porta al vero processo proprietario che vuoi sapere.

Quindi è sufficiente eseguire un passaggio aggiuntivo dal codice già esistente, è sufficiente enumerare le finestre secondarie e cercarne una con un processo proprietario diverso. Po 'di codice C, cercando di renderlo il più universale possibile senza fare troppi ipotesi e non abbastanza controllo degli errori:

#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; 
} 

uscita sul programma Meteo:

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

+0

Un'osservazione tardiva - Funziona in modalità finestra, non funziona con app UWP a schermo intero su Win10 (restituisce il pid ApplicationFrameHost.exe per entrambi i genitori e figlio nel percorso di enumerazione). – prabindh

10

Ecco una piccola applicazione per console che continuamente (quindi è possibile testarlo facilmente selezionando diverse finestre sul desktop) visualizza le informazioni sul processo corrente in primo piano e sul processo di archiviazione, se presenti.

Le applicazioni possono avere una gerarchia di finestre che può estendersi su più processi. Quello che faccio qui è cercare la prima finestra secondaria che ha il nome della classe 'Windows.UI.Core.CoreWindow'.

Questa applicazione utilizza lo UIAutomation API (e anche puntatori intelligenti, BSTR intelligenti e VARIANT intelligenti forniti dalla direttiva #import). Suppongo che tu possa fare lo stesso con l'SDK di Windows standard, ma trovo che UIAutomation sia usato in questo modo piuttosto elegante.

#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; 
} 
2

L'acquisizione dell'istantanea dei processi in esecuzione e l'estrazione del nome mediante il confronto dell'id del processo non funziona? riferimento completo qui:

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

Ma si fissa l'istantanea con CreateToolhelp32Snapshot().

O da WTSEnumerateProcesses() e l'API circostante?

Piuttosto sicuro che ha funzionato in Win 8. È rotto in 10?

+0

Confronto tra l'ID di processo e cosa? Le moderne applicazioni (in stile Windows Store) non possiedono finestre USER32 di livello superiore, quindi ottenere l'HWND corretto da passare a 'GetWindowThreadProcessId()' non è banale. –

+0

L'istantanea non richiede un hwnd. Può essere usato per ottenere un elenco di tutti i processi nel sistema. Quindi puoi filtrare una voce da quell'elenco in base a ciò che sai sul processo. Presumibilmente si conosce _qualcosa_ (come l'id del processo principale). –

+0

@Ben Voigt, rimuoverò il bit relativo a GetWindowThreadProcessId() poiché, come hai detto, non esiste hwnd. –

-2

a partire da finestra secondaria Win10 Anniversario Aggiornamento ApplicationFrameHost restituisce nulla ma l'applicazione UWP. Ha funzionato solo in modalità Tablet dopo il relogon.