2015-08-21 7 views
7

Ho un'applicazione Win32 che determina se sono visibili finestre visibili, non iconiche e minimizzabili. Per quanto ne so, ha funzionato bene per Win9x fino a Win8.1, ma in Windows 10 trova spesso diverse finestre che non sono effettivamente visibili sullo schermo.Come identificare i processi di archivio in background di Windows 10 con finestre non visualizzate che sono visibili e minimizzabili a livello di codice?

Per cercare di identificare cosa sta succedendo ho scritto una semplice applicazione di test che enumera e registra tutte queste finestre. Ecco l'essenza del codice EnumWindows callback:

BOOL CALLBACK EnumFunc(HWND hWnd, LPARAM lParam) 
{ 
    if (IsWindowVisible(hWnd)) 
    { 
    if (!IsIconic(hWnd)) 
    { 
     const LONG style = GetWindowLong(hWnd, GWL_STYLE); 

     if (WS_MINIMIZEBOX & style) 
     { 
    //  record window info 
     } 
    } 
    } 
return TRUE; 
} 

maggior parte delle finestre fantasma sotto Windows 10 appartengono a sfondo memorizzare i processi di applicazioni come Mail, Calcolatrice, e Foto. Questi sono elencati nella sezione Processi in background di Task Manager e, se utilizzo Task Manager per terminare le attività in background, la loro finestra fantasma non viene più trovata dalla mia applicazione di test.

enter image description here

Nella schermata sopra dalla mia applicazione di test si può vedere che tutti, ma 1 delle finestre offendere appartengono al thread dello stesso processo di identificazione 7768, che è ApplicationFrameHost.exe. La finestra finale con ID processo 11808 è explorer.exe.

Ho guardato le finestre fantasma con Spy ++ e non riesco a vedere nessuna particolare combinazione di stili che possa aiutare a identificarli in modo univoco.

che ho avuto un suggerimento che le "bande" senza documenti di Windows possono essere coinvolti, ma ho provato ad utilizzare il (non documentato, quindi questo potrebbe essere sbagliato) API:

BOOL WINAPI GetWindowBand (HWND hWnd, PDWORD pdwBand); 

ma restituisce un banda di 1 per qualsiasi finestra, quindi non differenzia questi fantocci.

Come identificare in modo affidabile queste finestre fantasma?

+0

fare quelle finestre capita di condividere la stessa classe di finestra? O forse hanno le stesse proprietà impostate (vedere [EnumProps] (https://msdn.microsoft.com/en-us/library/windows/desktop/ms633562.aspx))? Quando dici che * "l'API non documentata [...] restituisce una banda di 1" *, quale valore sta guardando? Il valore di ritorno 'BOOL', o' DWORD' indicato dal secondo parametro? – IInspectable

+0

Molti (non tutti quelli che ho incontrato) hanno lo stesso nome di classe della finestra, ma quando le applicazioni sono in esecuzione normalmente visibili sullo schermo, hanno ancora lo stesso nome di classe. –

+0

Per quanto riguarda la chiamata GetWindowBand, il valore di ritorno BOOL è sempre diverso da zero e il numero "banda" nel parametro pointer DWORD è sempre 1. –

risposta

0

Le finestre di livello superiore della classe ApplicationFrameWindow sono contenitori per le app di Windows Store. In primo luogo, qui è la finestra di Posta mostrata in Spy:

enter image description here

Questo è veramente visibile (non phantom). Si può dire che è perché il primo figlio è una finestra della classe Windows.UI.Core.CoreWindow. È interessante notare che il processo proprietario di ApplicationFrameWindow è APPLICATIONFRAMEHOST, ma il processo proprietario di Windows.UI.Core.CoreWindow è uno diverso uno: HXMAIL. (Non ho mai visto una finestra secondaria di proprietà di un processo diverso da quello genitore prima!)

Confronti che, con una finestra fantasma (come individuato nel vostro RWTool):

enter image description here

E ' manca il figlio della classe Windows.UI.Core.CoreWindow.

Questo suggerisce una risposta alla tua domanda: se una finestra di livello superiore è di classe ApplicationFrameWindow, iterare è figli. Se il primo figlio ha classe Windows.UI.Core.CoreWindow, la finestra è visibile, altrimenti non lo è (cioè è fantasma).

Ma cosa succede se un'app vecchio stile non store aveva una finestra di livello superiore della classe ApplicationFrameWindow?Non avrebbe un figlio di Windows.UI.Core.CoreWindow. Eppure è visibile. Come dire che questa è un'app normale e non un'app di Windows Store? Non ho un metodo infallibile. È anche possibile verificare l'esistenza delle altre finestre secondarie di un'app Store: ApplicationFrameTitleBarWindow e ApplicationFrameInputSinkWindow. Le probabilità che un'app non Store abbia questa esatta gerarchia di Windows è estremamente piccola.

EDIT

I ApplicationFrameWindow 's (e anche Windows.UI.Core.CoreWindow) hanno il set WS_EX_NOREDIRECTIONBITMAP stile:

la finestra non si rendono ad una superficie di reindirizzamento. Questo è per Windows che non hanno contenuto visibile o che usano meccanismi diversi dalle superfici per fornire il loro aspetto.

Come minimo, è possibile verificare questo stile anziché il case speciale ApplicationFrameWindow. Anche se per vedere se qualche contenuto era veramente visibile, dovresti comunque farlo a seconda che abbia un figlio di Windows.UI.Core.CoreWindow.

+0

Grazie a David, quel modello corrisponde a quello che vedo per le finestre dell'app store fantasma, tuttavia vedo anche un fantasma che appare per il processo Skype (ultima versione desktop) e che non ha finestre secondarie e ha la classe nome "TApplication", quindi non vedo che questo genere di cose sia una soluzione affidabile. –

+0

Sicuro David, ma non capisco come un'app Skype vecchio stile con un nome di classe di 'TApplication' invalida il rilevamento di un'app di Metro 'fantasma' rispetto a un'app 'Metro' reale? BTW, ho scaricato e installato l'ultimo Desktop Skype su Win 10, è la versione 7.8.0.102, e la finestra visibile con Contacts ha un nome di classe di 'tSkMainForm'. Trovo anche una finestra con la classe 'TApplication' ma la larghezza e l'altezza sono 0 in modo che non sia visibile. –

+0

Non è che il comportamento di Skype abbia invalidato in modo particolare qualsiasi cosa, solo che indicava che la soluzione potrebbe non essere robusta perché si basa solo sulle situazioni empiriche che stiamo vedendo. In effetti funziona come ti aspetteresti. Vorrei che ci fosse qualche documentazione concreta che potesse spiegare cosa sono queste cose e perché non sono visibili. Per inciso, come hai ottenuto il tuo sistema Win10 per avere queste finestre app non visibili - non ero in grado di farle accadere su una VM; mentre sul mio sistema host, sembrano solo sorgere alla fine senza che io faccia nulla! –

7

Il modo approvato di rilevare queste finestre fantasma consiste nell'utilizzare DwmGetWindowAttribute e DWMWA_CLOAKED.

Ecco il codice che ho usato:

static bool IsInvisibleWin10BackgroundAppWindow(HWND hWnd) 
{ 
    int CloakedVal; 
    HRESULT hRes = DwmGetWindowAttribute(hWnd, DWMWA_CLOAKED, &CloakedVal, sizeof(CloakedVal)); 
    if (hRes != S_OK) 
    { 
     CloakedVal = 0; 
    } 
    return CloakedVal ? true : false; 
} 

Grazie a Scot Br da MS per la pubblicazione la risposta here

+1

Anche Windows in un altro desktop verrà visualizzato come DWMWA_CLOAKED. Un modo migliore per farlo è utilizzare questa libreria: https://github.com/Grabacr07/VirtualDesktop Utilizzare il metodo VirtualDesktop.FromHwnd(), e se è null, significa che si tratta di un'app di Windows 10 in background. 'return VirtualDesktop.FromHwnd (hWnd) == null;' – AfzalivE

+1

@AfzalivE grazie !! Uso il codice di Grabacr07 nel mio progetto. https://github.com/mzomparelli/zVirtualDesktop –

+0

@MichaelZ. È fantastico! Sembra qualcosa che sto facendo troppo lol – AfzalivE

Problemi correlati