1

在引用同一应用程序的多个实例时,谁能想到 osascript index-by-name 瓶颈的解决方法?

如果我们获得两个进程 id——一个对应于同一应用程序的两个不同实例中的每一个,则 osascript 返回相同的实例以换取其中一个 pid——就好像它首先将 pid 映射到一个应用程序名称,然后检索第一个应用程序进程那个名字。

例如,启动两个不同的 VLC.app 实例,播放两个不同的视频文件,例如:

open -na /Applications/VLC.app ~/fileA.m4v
open -na /Applications/VLC.app ~/fileB.m4v

然后获取两个单独的应用程序进程 ID,例如:

echo "$(ps -ceo pid=,comm= | awk '/VLC/ { print $1}')"

然后,我们可以使用 Applescript 或 Yosemite JXA Javascript 从任一 pid 获取对应用程序对象的引用。

然而,事实证明,无论我们提供哪个进程 ID,我们总是返回对同一实例的引用,运行相同的视频文件,好像 osascript 只是将 pid 转换为应用程序名称,然后总是返回第一个进程匹配那个名字。

优胜美地 Javascript 应用程序:

function run() {
    var app = Application.currentApplication();
    app.includeStandardAdditions = true;

    var lstVLC = app.doShellScript(
            "echo \"$(ps -ceo pid=,comm= | awk '/VLC/ { print $1}')\""
        ).split(/[\r\n]/).map(Number).map(Application);

    return {
        firstInstance: lstVLC[0].windows[0].name(),
        secondInstance: lstVLC[1].windows[0].name()
    };
}

苹果脚本:

on run {}
    set strCMD to "echo \"$(ps -ceo pid=,comm= | awk '/VLC/ { print $1}')\""
    set lstNum to paragraphs of (do shell script strCMD)
    repeat with i from 1 to length of lstNum
        set item i of lstNum to (item i of lstNum) as number
    end repeat


    tell application "System Events"
        set oProcA to first application process where unix id = (item 1 of lstNum)
        set oProcB to first application process where unix id = (item 2 of lstNum)
    end tell

    return [name of first window of oProcA, name of first window of oProcB]
end run

关于分别为每个实例编写脚本的路线有什么想法吗?

4

4 回答 4

1

对于每个实例,从与特定进程相同的行中询问窗口的名称,如下所示:

set windowNames to {}
set lstNum to paragraphs of (do shell script "ps -ceo pid=,comm= | awk '/VLC/ { print $1}'")
tell application "System Events" to repeat with i in lstNum
    set end of windowNames to name of first window of (first application process where unix id = i)
end repeat
return windowNames
于 2015-04-01T13:40:39.770 回答
1

这似乎已在 El Capitan 中得到修复,因为您的 JavaScript 代码在我的机器上运行良好。

于 2015-07-20T20:01:56.377 回答
0

在 Javascript 中使用jackjr300的方法,至少获得 UI 脚本(虽然不是 Application 对象接口):

function run() {
    var appSE = Application("System Events");
    app = Application.currentApplication();

    app.includeStandardAdditions = true;

    function uiWidgets(lngID) {
        return appSE.processes.whose({
            unixId: lngID
        })[0].windows[0].uiElements();
    }

    var lstWidgets = app.doShellScript(
            "ps -ceo pid=,comm= | awk '/VLC/ { print $1}'"
        ).split(/\r/).map(Number).map(uiWidgets);

    return lstWidgets;
}
于 2015-04-01T15:53:19.740 回答
0

JXA 是一堆错误和有缺陷的设计。它没有做这样的事情令人沮丧的,但完全不足为奇(AS 团队有形式)。

至于 AppleScript,它从来没有提供直接的方法来通过 PID 定位应用程序。在过去,我可能通过启用远程 Apple 事件并使用eppc://USER@HOST/APPNAME?pid=PIDURL 定位进程来欺骗它,但如果我能让它工作,那么现在在 10.10 上尝试它该死的,因为它总是返回“不允许远程访问”错误。

Appscript 可以在睡梦中做这些事情,但由于 Apple 的碳战争和糟糕的“替换”Cocoa API 迫使它进入“遗留”状态,所以我放弃了公众对它的支持,所以你只能靠自己了。

官方支持的一个可行的选项是 OS X 的 Scripting Bridge 框架,它提供了一种通过 PID 定位进程的方法。尽管与 JXA 一样,它充满了设计缺陷、缺少功能和应用程序兼容性问题,所以 YMWV。

于 2015-04-01T17:03:24.640 回答