Come identificare quale processo sta eseguendo quale finestra in Mac OS X?


28

Vorrei sapere se è possibile identificare quale processo è responsabile della creazione / gestione di una finestra in Mac OS X.

Ad esempio, quando vengono avviate più istanze di un'applicazione, come posso ottenere l'ID processo (PID) corrispondente a una finestra specifica? Oppure, se esiste una finestra di dialogo modale senza titolo, come posso ottenere il PID del suo proprietario?

So che in Windows è possibile utilizzare lo strumento Sysinternals Suite che fornisce un modo per cercare una libreria in esecuzione con alcuni dati.

Sto cercando un meccanismo simile a quello che appare in questo post sul blog .

In questo caso, utilizzando Sysinternals Suite (e Process Explorer), hanno scoperto quale DLL / programma utilizzava la webcam cercando una DLL o una sottostringa (in questo caso, utilizzando il nome fisico del dispositivo).

Quindi esiste qualche meccanismo o programma o hai idea di come cercare qualcosa di simile per Mac OS X? Come posso identificare quale processo ha avviato una finestra?


"... quale processo mostra quale finestra ..." Questo è confuso rispetto all'esempio di Windows di "... quale DLL / programma utilizzava la webcam cercando una DLL o una sottostringa". Puoi chiarire la tua domanda per chiarire.
Jake Gould,

1
Alcuni processi sono in esecuzione senza finestre e forse anche senza un terminale di controllo.
Basile Starynkevitch,

Risposte:


22

Ho usato lo script Python . Non è infallibile, ma funziona abbastanza bene per me.

Non ripubblicherò lo script completo senza autorizzazione, ma ecco un riassunto: utilizza CGWindowListCopyWindowInfo, che viene importato Quartz, per raccogliere informazioni sulla finestra dal sistema, quindi chiede all'utente di spostare la finestra desiderata, quindi raccoglie nuovamente le informazioni sulla finestra e mostra informazioni per quelli che sono cambiati. Le informazioni scaricate includono l'ID del processo, come kCGWindowOwnerPID.

Ecco il codice:

#!/usr/bin/env python

import time
from Quartz import CGWindowListCopyWindowInfo, kCGWindowListExcludeDesktopElements, kCGNullWindowID
from Foundation import NSSet, NSMutableSet

wl1 = CGWindowListCopyWindowInfo(kCGWindowListExcludeDesktopElements, kCGNullWindowID)
print 'Move target window'
time.sleep(5)
wl2 = CGWindowListCopyWindowInfo(kCGWindowListExcludeDesktopElements, kCGNullWindowID)

w = NSMutableSet.setWithArray_(wl1)
w.minusSet_(NSSet.setWithArray_(wl2))
print '\nList of windows that moved:'
print w
print '\n'

Lo script stampa le informazioni per la finestra che ha cambiato posizione in un intervallo di 5 secondi. Quindi l'output è simile al seguente:

List of windows that moved:
{(
        {
        kCGWindowAlpha = 1;
        kCGWindowBounds =         {
            Height = 217;
            Width = 420;
            X = 828;
            Y = 213;
        };
        kCGWindowIsOnscreen = 1;
        kCGWindowLayer = 8;
        kCGWindowMemoryUsage = 406420;
        kCGWindowName = "";
        kCGWindowNumber = 77;
        kCGWindowOwnerName = UserNotificationCenter;
        kCGWindowOwnerPID = 481;
        kCGWindowSharingState = 1;
        kCGWindowStoreType = 2;
    }
)}

Bene, non è esattamente quello che stavo cercando, ma è un buon punto di partenza. Grazie @echo on!
I.Cougil,

@echo on - Non sono sicuro di come applicare ciò che mostra quel sito, potresti elaborare?
C_K,

Sembra che il link allo script Python sia morto. Credo di aver trovato lo stesso post su un nuovo sito di blog qui: cadebaba.blogspot.com/2014/04/…
Mark Ebbert

Questa è una sceneggiatura straordinaria. Mi ha aiutato a trovare software dannoso che non sono riuscito a identificare.
Samvel Avanesov,

SIMPATICO!! Questo è davvero il modo pulito e corretto per identificare e rimuovere malware che apre finestre di avviso. Molto meglio dell'installazione e dell'esecuzione di un programma antivirus che, chissà, potrebbe essere esso stesso un malware.
Jerry Krinock,

15

Ho creato uno strumento chiamato lswin

$ python lswin.py

    PID WinID  x,y,w,h                  [Title] SubTitle
------- -----  ---------------------    -------------------------------------------
    169  1956 {0,-38,1280,25        }   [Window Server] Backstop Menubar
    169  1955 {0,-60,1280,22        }   [Window Server] Menubar
    169   396 {0,-38,1280,25        }   [Window Server] Backstop Menubar
    169   395 {0,-60,1280,22        }   [Window Server] Menubar
    169     6 {0,0,0,0              }   [Window Server] Cursor
    169     4 {0,22,1280,25         }   [Window Server] Backstop Menubar
    169     3 {0,0,1280,22          }   [Window Server] Menubar
    169     2 {0,0,1280,800         }   [Window Server] Desktop
    262   404 {0,-38,1280,38        }   [Google Chrome] 
    262   393 {0,0,1280,800         }   [Google Chrome] 
    262   380 {100,100,1,1          }   [Google Chrome] Focus Proxy
    ... ...

Quindi puoi usare grep per trovare il pid della tua finestra.

Ecco il codice sorgente dello script:

#!/usr/bin/env python

import Quartz

#wl = Quartz.CGWindowListCopyWindowInfo( Quartz.kCGWindowListOptionOnScreenOnly | Quartz.kCGWindowListExcludeDesktopElements, Quartz.kCGNullWindowID)
wl = Quartz.CGWindowListCopyWindowInfo( Quartz.kCGWindowListOptionAll, Quartz.kCGNullWindowID)

wl = sorted(wl, key=lambda k: k.valueForKey_('kCGWindowOwnerPID'))

#print wl

print 'PID'.rjust(7) + ' ' + 'WinID'.rjust(5) + '  ' + 'x,y,w,h'.ljust(21) + ' ' + '\t[Title] SubTitle'
print '-'.rjust(7,'-') + ' ' + '-'.rjust(5,'-') + '  ' + '-'.ljust(21,'-') + ' ' + '\t-------------------------------------------'

for v in wl:
    print ( \
        str(v.valueForKey_('kCGWindowOwnerPID') or '?').rjust(7) + \
        ' ' + str(v.valueForKey_('kCGWindowNumber') or '?').rjust(5) + \
        ' {' + ('' if v.valueForKey_('kCGWindowBounds') is None else \
            ( \
                str(int(v.valueForKey_('kCGWindowBounds').valueForKey_('X')))     + ',' + \
                str(int(v.valueForKey_('kCGWindowBounds').valueForKey_('Y')))     + ',' + \
                str(int(v.valueForKey_('kCGWindowBounds').valueForKey_('Width'))) + ',' + \
                str(int(v.valueForKey_('kCGWindowBounds').valueForKey_('Height'))) \
            ) \
            ).ljust(21) + \
        '}' + \
        '\t[' + ((v.valueForKey_('kCGWindowOwnerName') or '') + ']') + \
        ('' if v.valueForKey_('kCGWindowName') is None else (' ' + v.valueForKey_('kCGWindowName') or '')) \
    ).encode('utf8')

Funziona perfettamente. Grazie per aver condiviso @ osexp2003!
Hay,

10

@kenorb Ho combinato le tue 2 versioni dello script, sostanzialmente funziona come la prima, mostrando differenza ma la formattazione è dalla seconda. Anche se la finestra non è sullo schermo - non viene stampata, altrimenti dà troppa spazzatura

import Quartz
import time
from Foundation import NSSet, NSMutableSet
def transformWindowData(data):
    list1 = []
    for v in data:
        if not v.valueForKey_('kCGWindowIsOnscreen'):
            continue


        row = ( \
            str(v.valueForKey_('kCGWindowOwnerPID') or '?').rjust(7) + \
            ' ' + str(v.valueForKey_('kCGWindowNumber') or '?').rjust(5) + \
            ' {' + ('' if v.valueForKey_('kCGWindowBounds') is None else \
                ( \
                    str(int(v.valueForKey_('kCGWindowBounds').valueForKey_('X')))     + ',' + \
                    str(int(v.valueForKey_('kCGWindowBounds').valueForKey_('Y')))     + ',' + \
                    str(int(v.valueForKey_('kCGWindowBounds').valueForKey_('Width'))) + ',' + \
                    str(int(v.valueForKey_('kCGWindowBounds').valueForKey_('Height'))) \
                ) \
                ).ljust(21) + \
            '}' + \
            '\t[' + ((v.valueForKey_('kCGWindowOwnerName') or '') + ']') + \
            ('' if v.valueForKey_('kCGWindowName') is None else (' ' + v.valueForKey_('kCGWindowName') or '')) \
        ).encode('utf8')
        list1.append(row)

    return list1;

def printBeautifully(dataSet):
    print 'PID'.rjust(7) + ' ' + 'WinID'.rjust(5) + '  ' + 'x,y,w,h'.ljust(21) + ' ' + '\t[Title] SubTitle'
    print '-'.rjust(7,'-') + ' ' + '-'.rjust(5,'-') + '  ' + '-'.ljust(21,'-') + ' ' + '\t-------------------------------------------'

    # print textList1
    for v in dataSet:
        print v;

#grab initial set
wl = Quartz.CGWindowListCopyWindowInfo( Quartz.kCGWindowListOptionAll, Quartz.kCGNullWindowID)
wl = sorted(wl, key=lambda k: k.valueForKey_('kCGWindowOwnerPID'))

#convert into readable format
textList1 = transformWindowData(wl);

#print everything we have on the screen
print 'all windows:'
printBeautifully(textList1)

print 'Move target window'
time.sleep(5)

#grab window data the second time
wl2 = Quartz.CGWindowListCopyWindowInfo(Quartz.kCGWindowListOptionAll, Quartz.kCGNullWindowID)
textList2 = transformWindowData(wl2)

#check the difference
w = NSMutableSet.setWithArray_(textList1)
w.minusSet_(NSSet.setWithArray_(textList2))

#print the difference
printBeautifully(w)

Fantastico. Un passo avanti verso xkill per Mac!
Michael Fox,

2
con un po 'dipip install pyobjc-framework-Quartz
CupawnTae

Si noti che lo script non funziona al 100% con le impostazioni multi-monitor. Se lo esegui in un terminale su una schermata e poi sposti la finestra su un'altra schermata, vedrai molte finestre elencate nel diff. Tutti sembrano finestre di sistema e icone nella barra dei menu, ecc. Meglio spostare il terminale e la finestra misteriosa sullo stesso schermo prima di eseguirlo.
DaveBurns
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.