在外部应用程序中获取当前文件Objective-C

时间:2014-04-21 05:57:09

标签: objective-c cocoa

我试图找出Mac OSX上其他活动应用程序当前打开的文件。我知道我可以通过以下方式打开当前的应用程序:

NSWorkspace *ws = [[NSWorkspace alloc] init];

NSArray *apps = [ws runningApplications];

// loop through the apps and get the localizedName

然而," runningApplications" (NSRunningApplication)并没有向我提供与该应用程序中的内容相关的任何内容。因此,让我们说用户已打开Sublime Text 2。我想访问该应用,看看他们当前在其中打开了哪些文档(以及该文档的相关路径)。

我知道AppleScript和脚本桥是"选项"但是,我在这些问题上看到的问题如下:

  • Scripting Bridge要求您从要连接的每个应用程序生成和添加头文件。 我的问题在于,我的应用程序并不知道用户提前拥有哪些应用。 XCode(5)似乎不允许我在安装时生成那些(即通过用户的应用程序目录循环并添加应用程序)或其他任何内容。

  • AppleScript虽然不依赖于您想要使用哪些应用程序,但并不适用于所有应用程序。只有某些人支持它。

此处的最终目标是能够查看用户当前打开的应用程序,并获取有关这些应用程序当前打开的内容的信息。

编辑:例如 - 如果用户有" /some/dir/example.txt"打开"文字编辑",我希望能够获取该信息。

4 个答案:

答案 0 :(得分:3)

要实现您的要求,您需要使用多个API进行主要工作。我们实现了这一点,我们花了几周的时间才完成它。这里有一些提示:

  • 使用NSRunningApplication获取Unix-PID
  • 使用AppleScript和AXAPI获取Windows及其文档。
    unixPID = 12345  -- insert the number here
    tell application id "com.apple.systemevents"
        try
            tell (application processes where unix id is unixPID)
                with timeout of 5 seconds
                    repeat with thiWind in every window
                        set isMain to value of attribute "AXMain" of thiWind
                        if isMain then
                            return value of attribute "AXDocument" of thiWind
                            exit repeat
                        end if
                    end repeat
                end timeout
            end tell
        end try
    end tell
  • 或/另外使用CGWindow.h来迭代所有应用程序的窗口,然后使用windows id和每个应用程序的特定脚本。 e.g:
tell application id "com.apple.TextEdit"
    try
        set mydoc to document of window id 1234 -- insert window number here
        return path of mydoc
    end try
end tell

要查看示例,check out our app。该功能实际上很难维护,并且在大多数情况下都能正常工作。请参阅Developer Section

中此页面上应如何实施其他应用

看到它的实际效果:

  • 将包含各种文档的文件夹添加到Raskin(例如,文字,数字,文字,Photoshop,...)
  • 在他们的应用程序中打开这些文档
  • 大多数文档会显示打开的徽章
  • 然后您可以使用cmd-alt-R或cmd-alt-scroll从任何打开的文档返回到Raskin的Surface,从而暴露此文件

Open In Badge on a Text Document

答案 1 :(得分:1)

您可以使用lsof(列表打开文件)命令获取所需信息。该命令将生成旨在由其他程序读取的输出,您可以使用NSTask / NSPipe从应用程序执行。

HTH

附录:有些东西是无价的......

我看到你已经开了一笔赏金,但有些东西是不能买的......你有没有考虑过你在问什么?

考虑lsof正在做什么 - 它报告操作系统为应用程序打开的文件;应用程序本身是一个黑盒子,操作系统维护有关打开文件的信息,lsof可以访问它。

您希望在应用程序的黑匣子内对等,并代表用户确定应用程序知道的文件。这样的文件在操作系统意义上可能根本不是“打开” - 应用程序可能已打开它,读取内容,然后关闭它。你觉得怎么可能发现这个?从黑匣子?

例如,有NSDocument可能会提供此信息,但即使如此,您如何从外部应用程序访问NSDocument数据结构?如果应用程序没有使用NSDocument

该怎么办?

从Apple获取TextEdit示例代码,不读它。在Xcode下运行一段时间并打开一些文件。现在点击调试暂停按钮。使用调试器命令(以及调试器可以调用应用程序中的方法)尝试发现打开文件的列表。您可以阅读NSDocument上想要帮助您的任何文档。如果您可以找到路径名,那么您就可以开始使用解决方案(无论调试者可以通过某种方式执行任何操作,您都可以从应用程序执行此操作,但这可能并不简单。)

另一种方法:默认文件夹使用帮助应用程序来跟踪打开和保存对话框的使用情况。其他程序修补其他系统API。如果采用类似的方法,您可以设计一个帮助程序来跟踪某些NSDocument API的使用,并以这种方式维护一个“打开”文档列表。它当然只适用于基于NSDocument的应用程序,并且仅适用于帮助程序运行时启动的应用程序(因此您需要一个守护程序)。

总结:你所要求的并不一定是不可能,但它肯定远非微不足道(除非框架被提供以提供这些信息,缺乏答案表明不是)。考虑一下你想要实现的目标,让你问这个问题,你能用另一种方式完成这项任务吗?

HTH

答案 2 :(得分:1)

您可以使用lsof命令。它将返回打开文件列表。

查看this帖子

答案 3 :(得分:1)

我建议您查看Accessibility API。使用Accessibility API,您可以浏览辅助功能对象树。应用程序是树的最重要部分。然后,您可以浏览所有应用程序菜单,特别是Window菜单项,它通常包含应用程序中可用的文档数组。 Accessibility API确实要求该进程受信任,并且有权查看其他应用程序。要进行粗略测试,以便您可以确信API具有您所需的功能,请使用Xcode附带的辅助功能检查器工具(至少5. +)。打开它时,您可以查看OSX应用程序可用的所有对象。我也使用Sublime Text。它将显示正在使用的文件,如果每个文件都在自己的窗口中。