简体   繁体   中英

Finding the Current Active Window in Mac OS X using Python

有没有办法在Mac OS X上使用Python在给定时间找到当前活动窗口的应用程序名称?

This should work:

#!/usr/bin/python

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

Only works on Leopard, or on Tiger if you have PyObjC installed and happen to point at the right python binary in line one (not the case if you've installed universal MacPython, which you'd probably want to do on Tiger). But Peter's answer with the Carbon way of doing this will probably be quite a bit faster, since importing anything from AppKit in Python takes a while, or more accurately, importing something from AppKit for the first time in a Python process takes a while.

If you need this inside a PyObjC app, what I describe will work great and fast, since you only experience the lag of importing AppKit once. If you need this to work as a command-line tool, you'll notice the performance hit. If that's relevant to you, you're probably better off building a 10 line Foundation command line tool in Xcode using Peter's code as a starting point.

The method in the accepted answer was deprecated in OS X 10.7+. The current recommended version would be the following:

from AppKit import NSWorkspace
active_app_name = NSWorkspace.sharedWorkspace().frontmostApplication().localizedName()
print(active_app_name)

First off, do you want the window or the application name? This isn't Windows—an application process on Mac OS X can have multiple windows. (Furthermore, this has also been true of Windows for a few years now, although I have no idea what the API looks like for that.)

Second, Carbon or Cocoa?

To get the active window in Cocoa:

window = NSApp.mainWindow()

To get the name of your process in Cocoa:

appName = NSProcessInfo.processInfo().processName()

Edit: Oh, I think I know what you want. The name of the frontmost process, right?

I don't think there's a way to do it in Cocoa, but here's how to do it in Carbon in C:

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

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

Remember to CFRelease(processName) when you're done with it.

I'm not sure what that will look like in Python, or if it's even possible. Python doesn't have pointers, which makes that tricky.

I know PyObjC would translate the latter argument to CopyProcessName into err, processName = CopyProcessName(…) , but the Carbon bindings don't rely on PyObjC (they're part of core Python 2), and I'm not sure what you do about the PSN either way.

I needed the current frontmost application in a Python script that arranges the windows nicely on my screen (see move_window ).

Of course, the complete credit goes to Peter! But here is the complete program:

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

Build with gcc -framework Carbon filename.c

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM