Поиск текущего активного окна в Mac OS X с использованием Python

18

Есть ли способ найти имя приложения текущего активного окна в данный момент в Mac OS X с помощью Python?

    
задан Moiz 16.12.2008 в 23:33
источник

4 ответа

24

Это должно работать:

#!/usr/bin/python

from AppKit import NSWorkspace
activeAppName = NSWorkspace.sharedWorkspace().activeApplication()['NSApplicationName']
print activeAppName

Работает только на Leopard или на Tiger, если у вас установлен PyObjC, и он указывает на правильный двоичный код python в строке 1 (не тот случай, если вы установили универсальный MacPython, который вы, вероятно, захотите сделать на Tiger ). Но ответ Питера на Carbon-способ сделать это, вероятно, будет намного быстрее, поскольку импорт чего-либо из AppKit в Python занимает некоторое время, или, точнее, импорт чего-либо из AppKit в первый раз в процессе Python занимает некоторое время.

Если вам нужно это в приложении PyObjC, то то, что я описываю, будет работать отлично и быстро, так как вы испытываете только задержку импорта AppKit один раз. Если вам нужно, чтобы это работало как инструмент командной строки, вы заметите поражение производительности. Если это имеет отношение к вам, вам, вероятно, лучше построить 10-строчный инструмент командной строки Foundation в Xcode с использованием кода Питера в качестве отправной точки.

    
ответ дан Dirk Stoop 17.12.2008 в 01:44
источник
13

Метод в принятом ответе был устаревшим в OS X 10.7+. Текущая рекомендуемая версия будет следующей:

from AppKit import NSWorkspace
active_app_name = NSWorkspace.sharedWorkspace().frontmostApplication().localizedName()
print(active_app_name)
    
ответ дан kmundnic 09.08.2014 в 02:20
источник
  • Это действительно помогает! Как мы можем получить заголовок активного окна? –  Jake W 16.01.2015 в 08:10
  • Я знаю, что это возможно сделать с помощью AppleScript (вызов его через osascript в Python), но, насколько мне известно, нет простого способа сделать это в Python. Вот ссылка, чтобы проверить информацию, которую вы можете получить, используя Cocoa: developer.apple.com/library/mac/documentation/Cocoa/Reference/... –  kmundnic 17.01.2015 в 14:49
  • Первоначально мы использовали AppleScript для получения текущего заголовка окна, которое отлично работало. Но это не сработало, если мы подписали приложение. И затем я нашел собственный API в Quartz, чтобы это сделать, и это решило нашу проблему. –  Jake W 18.01.2015 в 02:48
  • По какой-то причине это всегда давало мне название моего терминала. Принятый ответ получил это правильно. Я запускаю OS X 10.10. –  erb 05.03.2015 в 10:44
  • @Yehosef Как было предложено рецензентами, я добавил ответ на этот вопрос: stackoverflow.com/questions/28815863/..., что более актуально. В принципе, способ получить имя приложения - то же самое, родная часть, которую я нашел, - это получение заголовка окна с помощью Quartz. –  Jake W 22.05.2016 в 00:58
Показать остальные комментарии
6

Во-первых, вы хотите окно или имя приложения? Это не Windows-процесс приложения в Mac OS X может иметь несколько окон. (Кроме того, это также относится к Windows уже несколько лет, хотя я не знаю, как выглядит API для этого.)

Во-вторых, углерод или какао?

Чтобы получить активное окно в Cocoa:

window = NSApp.mainWindow()

Чтобы получить имя вашего процесса в Cocoa:

appName = NSProcessInfo.processInfo().processName()

Изменить: О, я думаю, я знаю, чего вы хотите. Имя самого первого процесса, не так ли?

Я не думаю, что есть способ сделать это в Cocoa, но вот как это сделать в Carbon in C:

ProcessSerialNumber psn = { 0L, 0L };
OSStatus err = GetFrontProcess(&psn);
/*error check*/

CFStringRef processName = NULL;
err = CopyProcessName(&psn, &processName);
/*error check*/

Помните CFRelease(processName) , когда вы закончите с ним.

Я не уверен, что это будет выглядеть на Python, или если это возможно. Python не имеет указателей, что делает это сложным.

Я знаю, что PyObjC переведет последний аргумент на CopyProcessName на err, processName = CopyProcessName(…) , но привязки Carbon не полагаются на PyObjC (они являются частью основного Python 2), и я не уверен, что вы делаете о PSN в любом случае.

    
ответ дан Peter Hosey 17.12.2008 в 00:52
источник
  • Что нам нужно импортировать, чтобы получить NSApp и NSProcessInto? –  GreenAsJade 26.01.2014 в 22:59
  • @GreenAsJade: Идёт ответ Дирка, предположительно, Фонд и AppKit. –  Peter Hosey 26.01.2014 в 23:34
1

Мне понадобилось текущее приложение на самом верхнем уровне в скрипте Python, который удобно устраивает окна на моем экране (см. move_window ).

Конечно, полный кредит принадлежит Питеру! Но вот полная программа:

#include <Carbon/Carbon.h>

int main(int, char) {
    ProcessSerialNumber psn = { 0L, 0L };
    OSStatus err = GetFrontProcess(&psn);

    CFStringRef processName = NULL;
    err = CopyProcessName(&psn, &processName);
    printf("%s\n", CFStringGetCStringPtr(processName, NULL));
    CFRelease(processName);
}

Создать с gcc -framework Carbon filename.c

    
ответ дан SirVer 03.01.2012 в 21:04
источник
  • Как это ответ для python? –  GreenAsJade 26.01.2014 в 22:56
  • Также не для Python, но для новой автоматизации JavaScript Yosemite вы можете использовать $ .NSWorkspace.sharedWorkspace.activeApplication.objectForKey ('NSApplicationName'). UTF8String ;. Вам нужно сначала импортировать это: ObjC.import ('AppKit'). –  SirVer 15.02.2015 в 09:49
  • На данный момент «CopyProcessName» явно отмечено устаревшим. –  Isilmë O. 19.04.2018 в 19:42