Как можно адресовать два экземпляра одного и того же приложения через osascript

Может ли кто-нибудь придумать обходной путь для узкого места в osascript-индексировании по имени в его ссылке на несколько экземпляров одного и того же приложения?

Если мы получаем два идентификатора процесса - по одному для каждого из двух разных экземпляров одного и того же приложения, osascript возвращает один и тот же экземпляр в обмен на любой pid - как если бы он сначала сопоставлял pid с именем приложения, а затем извлекает первый процесс приложения с это имя.

Например, запустите два разных экземпляра VLC.app, воспроизводя два разных видеофайла, примерно так:

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

затем получите два отдельных идентификатора процесса приложения, например:

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

Затем мы можем использовать Applescript или Yosemite JXA Javascript, чтобы получить ссылку на объект приложения из любого pid.

Однако оказывается, что какой бы идентификатор процесса мы ни указали, нам всегда возвращается ссылка на один и тот же экземпляр, выполняющий один и тот же видеофайл, как если бы osascript просто переводил pid в имя приложения, а затем всегда возвращает первый процесс, который совпадает с этим именем.

Yosemite 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

Есть какие-нибудь мысли по поводу сценария для каждого экземпляра отдельно?


person houthakker    schedule 01.04.2015    source источник


Ответы (4)


Для каждого экземпляра задайте имя окна в той же строке, что и конкретный процесс, например:

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
person jackjr300    schedule 01.04.2015
comment
Мы, безусловно, можем получить свойства, предоставляемые такими системными событиями, но это по-прежнему не позволяет нам получить объект приложения с возможностью сценария для каждого из экземпляров. Если, например, мы запрашиваем JXA Javascript для экземпляра приложения по pid, он просто дает нам первый экземпляр с соответствующей строкой имени, независимо от конкретного pid ... - person houthakker; 01.04.2015
comment
Но если подумать - ваш подход - хороший способ обойти объект Application и выполнить некоторые сценарии пользовательского интерфейса ... - person houthakker; 01.04.2015

Похоже, это было исправлено в El Capitan, так как ваш код JavaScript нормально работал на моей машине.

person syntaxera    schedule 20.07.2015

Используя подход jackjr300 в Javascript, чтобы получить хотя бы сценарий пользовательского интерфейса (но не интерфейс объекта приложения):

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;
}
person houthakker    schedule 01.04.2015

JXA - это совокупность ошибок и дефектного дизайна. Его неспособность сделать что-то вроде этого right удручает, но совершенно неудивительно (команда AS имеет форму).

Что касается AppleScript, он никогда не предоставлял прямого доступа к приложениям по PID. В прошлом я, возможно, обманул его, включив удаленные события Apple и нацелив процесс на eppc://USER@HOST/APPNAME?pid=PID URL, но попробовал это прямо сейчас на 10.10, черт возьми, если бы я смог заставить его работать, поскольку он всегда возвращал ошибку «удаленный доступ запрещен».

Appscript мог делать это во сне, но я отказался от общедоступной поддержки этого приложения из-за войны Apple. на Carbon и дрянных «заменяющих» API-интерфейсах Cocoa, переводящих его в «устаревший» статус, так что вы здесь сами по себе.

Единственный официально поддерживаемый вариант, который может работать, - это инфраструктура моста сценариев OS X, которая предоставляет метод для нацеливания процессов по PID. Хотя, как и JXA, он пронизан недостатками дизайна, отсутствующими функциями и проблемами совместимости приложений, поэтому YMWV.

person foo    schedule 01.04.2015