Mac OS X에서 어떤 프로세스가 실행 중인지 식별하는 방법은 무엇입니까?


28

Mac OS X에서 윈도우를 생성 / 관리하는 프로세스를 식별 할 수 있는지 알고 싶습니다.

예를 들어, 여러 응용 프로그램 인스턴스가 시작될 때 특정 창 하나에 해당하는 프로세스 ID (PID)를 얻으려면 어떻게해야합니까? 또는 제목이없는 모달 대화 상자 창이있는 경우 소유자의 PID를 어떻게 얻을 수 있습니까?

Windows에서 일부 데이터로 실행되는 라이브러리를 검색하는 방법을 제공하는 Sysinternals Suite 도구를 사용하는 것이 가능하다는 것을 알고 있습니다.

이 blogpost에 나타나는 것과 유사한 메커니즘을 찾고 있습니다.

이 경우 Sysinternals Suite (및 프로세스 탐색기)를 사용하여 DLL 또는 하위 문자열 (이 경우 장치의 실제 이름 사용)을 검색하여 웹캠을 사용중인 DLL / 프로그램을 찾았습니다.

메커니즘이나 프로그램이 있습니까, 아니면 Mac OS X와 ​​비슷한 것을 검색하는 방법에 대한 아이디어가 있습니까? 어떤 프로세스가 창을 시작했는지 식별하려면 어떻게해야합니까?


“… 어떤 프로세스가 어떤 창을 표시하고 있는지…”이것은“… DLL 또는 하위 문자열을 검색하여 웹캠을 사용하고있는 DLL / 프로그램”의 Windows 예와 비교할 때 혼동됩니다. 질문을 수정하여 명확하게 설명해 주시겠습니까?
— JakeGould

1
일부 프로세스는 창없이, 심지어 제어 터미널 없이도 실행 중입니다.
— Basile Starynkevitch

답변:


22

파이썬 스크립트를 사용했습니다 . 그것은 완벽하지는 않지만 나에게는 꽤 잘 작동합니다.

허가없이 전체 스크립트를 다시 게시하지는 않지만 요약은 다음과 같습니다. 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

파이썬 스크립트에 대한 링크가 죽은 것 같습니다. 나는 여기에 새로운 블로그 사이트에서 동일한 게시물을 발견 믿는다 cadebaba.blogspot.com/2014/04/...
— 마크 Ebbert

이것은 놀라운 스크립트입니다. 그것은 내가 식별 할 수없는 불쾌한 소프트웨어를 찾는 데 도움이되었습니다.
— Samvel Avanesov

좋은!! 이것은 실제로 경고 창을 표시하는 맬웨어를 식별하고 제거하는 깨끗하고 올바른 방법입니다. 안티 바이러스 프로그램을 설치하고 실행하는 것보다 훨씬 낫습니다.
— 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 나는 두 가지 버전의 스크립트를 결합했다. 기본적으로 첫 번째 스크립트처럼 작동하지만 차이점을 보여 주지만 형식은 두 번째입니다. 또한 창이 화면에없는 경우-인쇄되지 않고, 그렇지 않으면 너무 많은 쓰레기가 발생합니다

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)

환상적인. Mac 용 xkill에 한 걸음 더 다가 가십시오!
— Michael Fox

2
약간의pip install pyobjc-framework-Quartz
— CupawnTae

멀티 모니터 설정에서는 스크립트가 100 % 작동하지 않습니다. 이를 한 화면의 터미널에서 실행 한 다음 다른 화면에서 창을 이동하면 diff에 많은 창이 나열됩니다. 그것들은 모두 메뉴 막대 등의 시스템 창과 아이콘처럼 보입니다. 실행하기 전에 터미널과 미스터리 창을 같은 화면으로 옮기는 것이 가장 좋습니다.
— DaveBurns
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.