如何通过osascript解决同一应用程序的两个实例

时间:2015-04-01 12:46:16

标签: javascript applescript osascript jxa

在参考同一应用程序的多个实例时,有没有人能想到osascript逐个索引瓶颈的解决方法?

如果我们获得两个进程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转换为应用程序名称一样,然后始终返回与该名称匹配的第一个进程。

Yosemite Javascript for applications:

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

AppleScript的:

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 个答案:

答案 0 :(得分: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

答案 1 :(得分:1)

这似乎已在El Capitan修复,因为您的JavaScript代码在我的计算机上正常运行。

答案 2 :(得分:0)

在Javascript中使用jackjr300的方法,至少要获得UI脚本(但不是到应用程序对象界面):

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

答案 3 :(得分:0)

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

对于AppleScript,它从未提供过通过PID定位应用程序的直接方法。在过去,我可能通过启用远程Apple事件并使用eppc://USER@HOST/APPNAME?pid=PID网址定位该流程来欺骗它,但是如果我能够让它继续工作,那么在10.10时尝试它会因为它始终返回"不允许远程访问"错误。

Appscript可以在睡眠中完成这些工作,但由于Apple的“碳战争”和糟糕的“替换”,我dropped公众支持它。 Cocoa API迫使它进入"遗产"状态,所以你自己在那里。

可能有效的官方支持选项是OS X的Scripting Bridge框架,它提供了一种通过PID定位进程的方法。虽然像JXA一样,它充斥着设计缺陷,缺少功能和应用程序兼容性问题,所以YMWV。