วิธีการระบุกระบวนการที่ใช้หน้าต่างใดใน Mac OS X


28

ฉันต้องการทราบว่าเป็นไปได้หรือไม่ที่จะระบุว่ากระบวนการใดรับผิดชอบในการสร้าง / จัดการหน้าต่างใน Mac OS X

ตัวอย่างเช่นเมื่อเริ่มต้นแอปพลิเคชันหลายอินสแตนซ์ฉันจะรับ ID กระบวนการ (PID) ที่สอดคล้องกับหน้าต่างใดหน้าต่างหนึ่งได้อย่างไร หรือถ้ามีหน้าต่างข้อความแบบโมดัลที่ไม่มีชื่อฉันจะรับ PID ของเจ้าของได้อย่างไร

ฉันรู้ว่าใน Windows มันเป็นไปได้โดยใช้เครื่องมือSysinternals Suiteที่ให้วิธีการค้นหาไลบรารีที่กำลังทำงานกับข้อมูลบางอย่าง

ฉันกำลังมองหากลไกที่คล้ายกับกลไกที่ปรากฏในบล็อกนี้

ในกรณีนี้การใช้ Sysinternals Suite (และ Process Explorer) พวกเขาพบว่า DLL / โปรแกรมใดกำลังใช้เว็บแคมโดยการค้นหา DLL หรือซับสตริง (ในกรณีนี้โดยใช้ชื่อทางกายภาพของอุปกรณ์)

ดังนั้นจึงมีกลไกหรือโปรแกรมหรือคุณมีความคิดเกี่ยวกับวิธีค้นหาสิ่งที่คล้ายกันสำหรับ Mac OS X ฉันจะระบุกระบวนการที่เปิดหน้าต่างได้อย่างไร


“ …กระบวนการใดที่แสดงว่าหน้าต่างใด…” นี่เป็นสิ่งที่สับสนเมื่อเปรียบเทียบกับตัวอย่าง Windows ของคุณที่“ ... โปรแกรม / DLL ตัวใดกำลังใช้เว็บแคมด้วยการค้นหา DLL หรือซับสตริง” คุณสามารถแก้ไขคำถามเพื่อชี้แจงได้
JakeGould

1
กระบวนการบางอย่างกำลังทำงานโดยไม่มีหน้าต่างใด ๆ และอาจถึงแม้จะไม่มีเทอร์มินัลการควบคุม
Basile Starynkevitch

คำตอบ:


22

ฉันใช้สคริปต์ Python มันไม่ผิดพลาด แต่ใช้งานได้ดีสำหรับฉัน

ฉันจะไม่โพสต์สคริปต์แบบเต็มโดยไม่ได้รับอนุญาต แต่นี่เป็นบทสรุป: มันใช้CGWindowListCopyWindowInfoซึ่งนำเข้าจากQuartzเพื่อรวบรวมข้อมูลหน้าต่างจากระบบจากนั้นขอให้ผู้ใช้ย้ายหน้าต่างที่ต้องการจากนั้นรวบรวมข้อมูลหน้าต่างอีกครั้งและแสดง ข้อมูลสำหรับรายการที่เปลี่ยนแปลง ข้อมูลทิ้งรวมถึงกระบวนการ ID kCGWindowOwnerPIDเป็น

นี่คือรหัส:

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

สคริปต์พิมพ์ข้อมูลสำหรับหน้าต่างที่เปลี่ยนตำแหน่งภายในช่วงเวลา 5 วินาที ดังนั้นผลลัพธ์จะเป็นดังนี้:

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

ไม่ใช่สิ่งที่ฉันกำลังมองหา แต่มันก็เป็นจุดเริ่มต้นที่ดี ขอบคุณ @echo บน!
I.Cougil

@echo on - ฉันไม่แน่ใจว่าจะใช้สิ่งที่แสดงให้เห็นว่าเว็บไซต์คุณช่วยให้รายละเอียด?
C_K

ดูเหมือนว่าลิงก์ไปยังสคริปต์ python นั้นตายแล้ว ฉันเชื่อว่าฉันพบโพสต์เดียวกันในเว็บไซต์บล็อกใหม่ที่นี่: cadebaba.blogspot.com/2014/04/…
Mark Ebbert

นี่เป็นสคริปต์ที่น่าทึ่ง มันช่วยให้ฉันพบซอฟต์แวร์ที่น่ารังเกียจซึ่งฉันไม่สามารถระบุได้
Samvel Avanesov

NICE !! นี่เป็นวิธีที่สะอาดและถูกต้องในการระบุและลบมัลแวร์ที่ปรากฏขึ้นหน้าต่างแจ้งเตือน ดีกว่าการติดตั้งและใช้งานโปรแกรมป้องกันไวรัสซึ่งรู้ว่าตัวเองอาจเป็นมัลแวร์
Jerry Krinock

15

ฉันทำเครื่องมือชื่อ 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
    ... ...

จากนั้นคุณสามารถใช้ grep เพื่อค้นหา pid ของหน้าต่าง

นี่คือซอร์สโค้ดของสคริปต์:

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

10

@kenorb ฉันรวมสคริปต์ 2 เวอร์ชันของคุณเข้าด้วยกันโดยทั่วไปแล้วมันทำงานเหมือนกับเวอร์ชั่นแรกซึ่งแสดงความแตกต่าง แต่การจัดรูปแบบมาจากครั้งที่สอง นอกจากนี้หากหน้าต่างไม่ได้อยู่บนหน้าจอ - มันไม่ได้ถูกพิมพ์มิฉะนั้นจะทำให้เกิดขยะมากเกินไป

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)

น่าอัศจรรย์ ขั้นตอนเดียวใกล้เคียงกับ xkill สำหรับ Mac!
Michael Fox

2
ด้วยนิด ๆ หน่อย ๆ ของpip install pyobjc-framework-Quartz
CupawnTae

โปรดทราบว่าสคริปต์ใช้งานไม่ได้ 100% กับการตั้งค่าหลายจอภาพ หากคุณรันสิ่งนี้ในเทอร์มินัลหนึ่งหน้าจอแล้วย้ายหน้าต่างไปที่อีกหน้าจอหนึ่งคุณจะเห็นหน้าต่างจำนวนมากที่แสดงอยู่ในส่วนต่าง ดูเหมือนว่าพวกเขาทั้งหมดจะเป็นหน้าต่างระบบและไอคอนในแถบเมนู ฯลฯ ควรย้ายเทอร์มินัลและหน้าต่างลึกลับไปยังหน้าจอเดียวกันก่อนเริ่มใช้งาน
DaveBurns
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.