Comment identifier quel processus exécute quelle fenêtre dans Mac OS X?

28

Je voudrais savoir s'il est possible d'identifier quel processus est responsable de la création / gestion d'une fenêtre sous Mac OS X.

Par exemple, lorsque plusieurs instances d'une application sont démarrées, comment puis-je obtenir l'ID de processus (PID) correspondant à une fenêtre spécifique? Ou s'il y a une fenêtre de dialogue modale sans titre, comment puis-je obtenir le PID de son propriétaire?

Je sais que sous Windows, il est possible d'utiliser l' outil Sysinternals Suite qui permet de rechercher une bibliothèque qui s'exécute avec certaines données.

Je recherche un mécanisme similaire à celui qui apparaît dans ce blog .

Dans ce cas, en utilisant Sysinternals Suite (et Process Explorer), ils ont trouvé la DLL / le programme qui utilisait la webcam en recherchant une DLL ou une sous-chaîne (dans ce cas, en utilisant le nom physique du périphérique).

Existe-t-il un mécanisme ou un programme, ou avez-vous une idée de la façon de rechercher quelque chose de similaire pour Mac OS X? Comment identifier quel processus a lancé une fenêtre?

I.Cougil
la source
"... quel processus montre quelle fenêtre ..." Cela est déroutant par rapport à votre exemple Windows de "... quelle DLL / programme utilisait la webcam en recherchant une DLL ou une sous-chaîne". Pouvez-vous modifier votre question pour clarifier.
JakeGould
1
Certains processus s'exécutent sans aucune fenêtre, et peut-être même sans terminal de contrôle.
Basile Starynkevitch

Réponses:

22

J'ai utilisé le script Python . Ce n'est pas infaillible, mais cela fonctionne assez bien pour moi.

Je ne publierai pas le script complet sans autorisation, mais voici un résumé: il utilise CGWindowListCopyWindowInfo, qui est importé de Quartz, pour collecter les informations de fenêtre du système, puis demande à l'utilisateur de déplacer la fenêtre souhaitée, puis recueille à nouveau les informations de fenêtre et affiche info pour ceux qui ont changé. Les informations sauvegardées incluent l'ID de processus, comme kCGWindowOwnerPID.

Voici le code:

#!/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'

Le script imprime des informations pour la fenêtre qui a changé de position dans un intervalle de 5 secondes. La sortie ressemble donc à ceci:

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;
    }
)}
écho sur
la source
Eh bien, ce n'est pas exactement ce que je cherchais, mais c'est un bon point de départ. Merci @echo sur!
I.Cougil
@echo on - Je ne sais pas comment appliquer ce que ce site montre, pourriez-vous élaborer?
C_K
On dirait que le lien vers le script python est mort. Je crois avoir trouvé le même message sur un nouveau site de blog ici: cadebaba.blogspot.com/2014/04/…
Mark Ebbert
Ceci est un script incroyable. Cela m'a aidé à trouver un logiciel méchant que je ne pouvais pas identifier.
Samvel Avanesov
AGRÉABLE!! Il s'agit en effet de la méthode propre et correcte pour identifier et supprimer les logiciels malveillants qui font apparaître des fenêtres d'alerte. Bien mieux que d'installer et d'exécuter un programme antivirus qui, qui sait, peut être lui-même un malware.
Jerry Krinock
15

J'ai fait un outil nommé 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
    ... ...

Ensuite, vous pouvez utiliser grep pour trouver le pid de votre fenêtre.

Voici le code source du 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')
osexp2003
la source
Fonctionne parfaitement. Merci d'avoir partagé @ osexp2003!
Hay
10

@kenorb J'ai combiné vos 2 versions du script, en gros cela fonctionne comme la première, montrant la différence mais le formatage est de la seconde. De plus, si la fenêtre n'est pas à l'écran - elle n'est pas imprimée, sinon elle donne trop de déchets

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)
Ruzard
la source
Fantastique. Un pas de plus vers xkill pour Mac!
Michael Fox
2
avec un peu depip install pyobjc-framework-Quartz
CupawnTae
Notez que le script ne fonctionne pas à 100% avec des configurations multi-écrans. Si vous exécutez cela dans un terminal sur un écran, puis déplacez la fenêtre sur un autre écran, vous verrez de nombreuses fenêtres répertoriées dans le diff. Tous semblent être des fenêtres système et des icônes dans la barre de menus, etc. Il est préférable de déplacer votre terminal et la fenêtre mystère sur le même écran avant de démarrer.
DaveBurns