¿Cómo identificar qué proceso está ejecutando qué ventana en Mac OS X?


28

Me gustaría saber si es posible identificar qué proceso es responsable de crear / administrar una ventana en Mac OS X.

Por ejemplo, cuando se inician varias instancias de una aplicación, ¿cómo puedo obtener el ID de proceso (PID) correspondiente a una ventana específica? O si hay una ventana de diálogo modal sin título, ¿cómo puedo obtener el PID de su propietario?

Sé que en Windows es posible usar la herramienta Sysinternals Suite que proporciona una forma de buscar una biblioteca que se ejecuta con algunos datos.

Estoy buscando un mecanismo similar al que aparece en este blog .

En este caso, usando Sysinternals Suite (y Process Explorer), encontraron qué DLL / programa estaba usando la cámara web buscando una DLL o una subcadena (en este caso, usando el nombre físico del dispositivo).

Entonces, ¿hay algún mecanismo o programa, o tienes alguna idea sobre cómo buscar algo similar para Mac OS X? ¿Cómo puedo identificar qué proceso ha lanzado una ventana?


"... qué proceso muestra qué ventana ..." Esto es confuso en comparación con su ejemplo de Windows de "... qué DLL / programa estaba usando la cámara web buscando una DLL o una subcadena". ¿Puede editar su pregunta para aclararla?
JakeGould

1
Algunos procesos se ejecutan sin ventanas, y tal vez incluso sin un terminal de control.
Basile Starynkevitch

Respuestas:


22

He usado el script Python . No es infalible, pero funciona bastante bien para mí.

No volveré a publicar el script completo sin permiso, pero aquí hay un resumen: utiliza CGWindowListCopyWindowInfo, que se importa Quartz, para recopilar información de la ventana del sistema, luego le pide al usuario que mueva la ventana deseada, luego recopila la información de la ventana nuevamente y muestra información para los que cambiaron. La información volcada incluye la ID del proceso, como kCGWindowOwnerPID.

Aquí está el código:

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

El script imprime información para la ventana que cambió de posición dentro de un intervalo de 5 segundos. Entonces la salida se ve así:

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

Bueno, no es exactamente lo que estaba buscando, pero es un buen punto de partida. Gracias @echo on!
I.Cougil

@echo on - No estoy seguro de cómo aplicar lo que muestra ese sitio, ¿podría explicarlo?
C_K

Parece que el enlace al script de Python está muerto. Creo que encontré la misma publicación en un nuevo sitio de blog aquí: cadebaba.blogspot.com/2014/04/…
Mark Ebbert

Este es un guión increíble. Me ayudó a encontrar un software desagradable que no pude identificar.
Samvel Avanesov

¡¡BONITO!! De hecho, esta es la forma limpia y correcta de identificar y eliminar el malware que aparece en las ventanas de alerta. Mucho mejor que instalar y ejecutar un programa antivirus que, quién sabe, puede ser malware.
Jerry Krinock

15

Hice una herramienta llamada 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
    ... ...

Entonces puedes usar grep para encontrar el pid de tu ventana.

Aquí está el código fuente del 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')

Funciona perfectamente. ¡Gracias por compartir @ osexp2003!
Hay

10

@kenorb Combiné tus 2 versiones del script, básicamente funciona como la primera, mostrando diferencias pero el formato es la segunda. Además, si la ventana no está en la pantalla, no se está imprimiendo, de lo contrario, genera demasiada basura

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)

Fantástico. ¡Un paso más cerca de xkill para Mac!
Michael Fox

2
con un poco depip install pyobjc-framework-Quartz
CupawnTae

Tenga en cuenta que el script no funciona al 100% con configuraciones de varios monitores. Si ejecuta esto en un terminal en una pantalla y luego mueve la ventana en otra pantalla, verá muchas ventanas enumeradas en el diff. Todos parecen ser ventanas e iconos del sistema en la barra de menú, etc. Lo mejor es mover su terminal y la ventana misteriosa a la misma pantalla antes de ejecutar.
DaveBurns
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.