【问题标题】:Finding the Current Active Window in Mac OS X using Python使用 Python 在 Mac OS X 中查找当前活动窗口
【发布时间】:2010-09-27 05:53:30
【问题描述】:

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

【问题讨论】:

    标签: python objective-c cocoa macos


    【解决方案1】:

    首先,您想要窗口还是应用程序名称?这不是 Windows——Mac OS X 上的一个应用程序进程可以有多个窗口。 (此外,Windows 几年来也是如此,尽管我不知道 API 是什么样子的。)

    第二,碳还是可可?

    在 Cocoa 中获取活动窗口:

    window = NSApp.mainWindow()
    

    在 Cocoa 中获取进程的名称:

    appName = NSProcessInfo.processInfo().processName()
    

    编辑:哦,我想我知道你想要什么。最前面的进程的名字吧?

    我认为在 Cocoa 中没有办法做到这一点,但这里是如何在 C 中的 Carbon 中做到这一点:

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

    完成后记得CFRelease(processName)

    我不确定这在 Python 中会是什么样子,或者是否有可能。 Python 没有指针,这很棘手。

    我知道 PyObjC 会将后一个参数转换为 CopyProcessNameerr, processName = CopyProcessName(…),但 Carbon 绑定不依赖于 PyObjC(它们是核心 Python 2 的一部分),我不确定你在做什么关于 PSN 的任何一种方式。

    【讨论】:

    • 我们需要导入什么来获取 NSApp 和 NSProcessInto?
    • @GreenAsJade:按照 Dirk 的回答,大概是 Foundation 和 AppKit。
    • 由于最初的问题是关于 Python,请注意 CFRelease 对于 PyObjC 不是必需的。 PyObjC 为您处理调用,AFAIK。
    【解决方案2】:

    这应该可行:

    #!/usr/bin/python
    
    from AppKit import NSWorkspace
    activeAppName = NSWorkspace.sharedWorkspace().activeApplication()['NSApplicationName']
    print activeAppName
    

    仅适用于 Leopard 或 Tiger 如果您安装了 PyObjC 并且恰好在第一行指向正确的 python 二进制文件(如果您安装了通用 MacPython,则情况并非如此,您可能希望在 Tiger 上执行此操作)。但是 Peter 对 Carbon 方法的回答可能会快很多,因为在 Python 中从 AppKit 导入任何东西需要一段时间,或者更准确地说,在 Python 进程中第一次从 AppKit 导入一些东西需要一段时间。

    如果您在 PyObjC 应用程序中需要它,我所描述的将非常有效且快速,因为您只体验一次导入 AppKit 的延迟。如果您需要它作为命令行工具工作,您会注意到性能下降。如果这与您相关,您最好使用 Peter 的代码作为起点,在 Xcode 中构建一个 10 行的 Foundation 命令行工具。

    【讨论】:

      【解决方案3】:

      我需要一个 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”已被明确标记为已弃用。
      【解决方案4】:

      已接受答案中的方法在 OS X 10.7+ 中已弃用。当前推荐的版本如下:

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

      【讨论】:

      • 这真的很有帮助!我们如何获取活动窗口标题?
      • 我知道可以使用 AppleScript(在 Python 中通过 osascript 调用它)来实现,但据我所知,在 Python 中没有直接的方法。这里有一个链接可以检查您可以使用 Cocoa 检索到的信息:developer.apple.com/library/mac/documentation/Cocoa/Reference/…
      • 最初我们使用 AppleScript 来获取当前窗口标题,效果很好。但如果我们签署了应用程序,它就不起作用了。然后我在 Quartz 中找到了一个原生 API 来做这件事,这解决了我们的问题。
      • 出于某种原因,这总是给我终端的名称。接受的答案是正确的。我正在运行 OS X 10.10。
      • @Yehosef 根据审稿人的建议,我添加了这个问题的答案:stackoverflow.com/questions/28815863/…,这更相关。基本上获取应用名称的方法是一样的,我发现的原生部分是使用 Quartz 获取窗口标题。
      猜你喜欢
      • 2010-10-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-14
      相关资源
      最近更新 更多