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






Во-первых, вам нужно окно или название приложения? Это не Windows - процесс приложения в Mac OS X может иметь несколько окон. (Более того, уже несколько лет это относится и к Windows, хотя я понятия не имею, как выглядит API для этого.)
Во-вторых, углерод или какао?
Чтобы получить активное окно в Какао:
window = NSApp.mainWindow()
Чтобы получить имя вашего процесса в Какао:
appName = NSProcessInfo.processInfo().processName()
Редактировать: О, думаю, я знаю, чего вы хотите. Название самого переднего процесса, верно?
Я не думаю, что есть способ сделать это в Cocoa, но вот как это сделать в Carbon на 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 в любом случае.
@GreenAsJade: Исходя из ответа Дирка, предположительно Foundation и AppKit.
Поскольку исходный вопрос касался Python, обратите внимание, что CFRelease не требуется с PyObjC. PyObjC обрабатывает это за вас, AFAIK.
Это должно работать:
#!/usr/bin/python
from AppKit import NSWorkspace
activeAppName = NSWorkspace.sharedWorkspace().activeApplication()['NSApplicationName']
print activeAppName
Работает только на Leopard или на Tiger, если у вас установлен PyObjC и случайно указывает на правильный двоичный файл python в первой строке (не тот случай, если вы установили универсальный MacPython, что вы, вероятно, захотите сделать на Tiger). Но ответ Питера с углеродным способом сделать это, вероятно, будет немного быстрее, поскольку импорт чего-либо из AppKit в Python занимает некоторое время, а точнее, импорт чего-либо из AppKit в первый раз в процессе Python занимает некоторое время.
Если вам это нужно внутри приложения PyObjC, то, что я описываю, будет работать отлично и быстро, поскольку вы испытываете задержку при импорте AppKit только один раз. Если вам нужно, чтобы это работало как инструмент командной строки, вы заметите снижение производительности. Если это актуально для вас, вам, вероятно, лучше создать 10-строчный инструмент командной строки Foundation в Xcode, используя код Питера в качестве отправной точки.
Мне нужно было текущее самое переднее приложение в скрипте 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
Как это ответ для Python?
Также не для Python, но для новой автоматизации Yosemite JavaScript вы можете использовать $.NSWorkspace.sharedWorkspace.activeApplication.objectForKey('NSApplicationName').UTF8String;. Однако сначала вам нужно импортировать это: ObjC.import('AppKit').
На данный момент CopyProcessName явно помечено как устаревшее.
Метод в принятом ответе устарел в OS X 10.7+. Текущая рекомендуемая версия будет следующей:
from AppKit import NSWorkspace
active_app_name = NSWorkspace.sharedWorkspace().frontmostApplication().localizedName()
print(active_app_name)
Это действительно помогает! Как мы можем получить заголовок активного окна?
Я знаю, что это можно сделать с помощью AppleScript (вызывая его через osascript в Python), но, насколько мне известно, на Python нет простого способа сделать это. Вот ссылка для проверки информации, которую вы можете получить с помощью Какао: developer.apple.com/library/mac/documentation/Cocoa/Referenc e /…
Первоначально мы использовали AppleScript для получения текущего заголовка окна, что отлично работало. Но это не сработало, если мы подписали приложение. А затем я нашел собственный API в Quartz для этого, и это решило нашу проблему.
По какой-то причине это всегда давало мне имя моего терминала. В принятом ответе все было правильно. Я использую OS X 10.10.
@JakeW - не могли бы вы рассказать, как вам это удалось? что за API?
@Yehosef Я добавил новый ответ, чтобы он мог отображать образец кода в лучшем формате. Надеюсь, это будет вам полезно.
@JakeW - спасибо! Но где ответ? Я этого не вижу.
@Yehosef По мнению обозревателей, я добавил ответ на этот вопрос: stackoverflow.com/questions/28815863/…, что более актуально. В основном способ получения имени приложения такой же, нативная часть, которую я нашел, предназначена для получения заголовка окна с помощью Quartz.
Что нам нужно импортировать, чтобы получить NSApp и NSProcessInto?