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.