Bagaimana cara mengidentifikasi proses mana yang menjalankan jendela mana di Mac OS X?

28

Saya ingin tahu apakah mungkin mengidentifikasi proses mana yang bertanggung jawab untuk membuat / mengelola jendela di Mac OS X.

Misalnya, ketika beberapa contoh aplikasi dimulai, bagaimana saya bisa mendapatkan ID proses (PID) yang sesuai dengan satu jendela tertentu? Atau jika ada jendela dialog modal tanpa judul, bagaimana saya bisa mendapatkan PID pemiliknya?

Saya tahu di Windows dimungkinkan menggunakan alat Sysinternals Suite yang menyediakan cara untuk mencari perpustakaan yang berjalan dengan beberapa data.

Saya mencari mekanisme yang mirip dengan yang muncul di blogpost ini .

Dalam hal ini, menggunakan Sysinternals Suite (dan Process Explorer), mereka menemukan DLL / program mana yang menggunakan webcam dengan mencari DLL atau substring (dalam hal ini, menggunakan nama fisik perangkat).

Jadi apakah ada mekanisme atau program, atau apakah Anda punya ide tentang cara mencari sesuatu yang mirip untuk Mac OS X? Bagaimana saya bisa mengidentifikasi proses mana yang telah meluncurkan jendela?

I.Cougil
sumber
"... proses mana yang menunjukkan jendela mana ..." Ini membingungkan jika dibandingkan dengan contoh Windows Anda tentang "... DLL / program mana yang menggunakan webcam dengan mencari DLL atau substring." Bisakah Anda mengedit pertanyaan Anda untuk menjelaskan.
JakeGould
1
Beberapa proses berjalan tanpa jendela apa pun, dan mungkin bahkan tanpa terminal pengendali.
Basile Starynkevitch

Jawaban:

22

Saya telah menggunakan skrip Python . Ini tidak mudah, tetapi itu bekerja cukup baik untuk saya.

Saya tidak akan memposting ulang skrip lengkap tanpa izin, tetapi inilah ringkasannya: Ini menggunakan CGWindowListCopyWindowInfo, yang diimpor dari Quartz, untuk mengumpulkan informasi jendela dari sistem, kemudian meminta pengguna untuk memindahkan jendela yang diinginkan, kemudian mengumpulkan informasi jendela lagi, dan menunjukkan info untuk yang berubah. Info yang dibuang termasuk ID proses, sebagai kCGWindowOwnerPID.

Ini kodenya:

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

Script mencetak informasi untuk jendela yang mengubah posisi dalam interval 5 detik. Jadi outputnya terlihat seperti ini:

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;
    }
)}
gema terus
sumber
Yah, itu tidak persis apa yang saya cari, tetapi itu adalah titik awal yang baik. @Echo terima kasih!
I.Cougil
@echo aktif - Saya tidak yakin bagaimana menerapkan apa yang ditampilkan situs itu, dapatkah Anda menguraikan?
C_K
Sepertinya tautan ke skrip python sudah mati. Saya yakin saya menemukan posting yang sama di situs blog baru di sini: cadebaba.blogspot.com/2014/04/…
Mark Ebbert
Ini skrip yang luar biasa. Ini membantu saya menemukan perangkat lunak yang tidak dapat saya identifikasi.
Samvel Avanesov
BAGUS!! Ini memang cara bersih dan benar untuk mengidentifikasi dan menghapus malware yang muncul jendela peringatan. Jauh lebih baik daripada menginstal dan menjalankan program antivirus yang, siapa tahu, itu sendiri mungkin malware.
Jerry Krinock
15

Saya membuat alat bernama 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
    ... ...

Kemudian Anda dapat menggunakan grep untuk menemukan pid jendela Anda.

Berikut adalah kode sumber skrip:

#!/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
sumber
Bekerja dengan sempurna. Terima kasih telah berbagi @ osexp2003!
Hay
10

@kenorb Saya menggabungkan 2 versi skrip Anda, pada dasarnya ini berfungsi seperti yang pertama, menunjukkan perbedaan tetapi memformat dari yang kedua. Juga jika jendela tidak ada di layar - tidak dicetak, jika tidak akan menghasilkan terlalu banyak sampah

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
sumber
Fantastis. Satu langkah lebih dekat ke xkill untuk Mac!
Michael Fox
2
dengan sedikitpip install pyobjc-framework-Quartz
CupawnTae
Perhatikan bahwa skrip tidak berfungsi 100% dengan pengaturan multi-monitor. Jika Anda menjalankan ini di terminal pada satu layar dan kemudian memindahkan jendela di layar lain, Anda akan melihat banyak jendela terdaftar di diff. Semuanya tampak sebagai sistem windows dan ikon di bilah menu, dll. Terbaik untuk memindahkan terminal Anda dan jendela misteri ke layar yang sama sebelum berjalan.
DaveBurns