2015-04-01 1 views
0

Quelqu'un peut-il penser à une solution de contournement pour l'index-par-nom bouteille-cou dans sa référence à plusieurs instances de la même application?Comment peut-on adresser deux instances de la même application par l'intermédiaire d'osascript

Si nous obtenons deux identifiants de processus - un pour chacune des instances différentes de la même application, osascript renvoie la même instance en échange de l'un ou l'autre - comme s'il mappait d'abord le pid à un nom d'application, puis récupérait le premier processus de demande avec ce nom.

Par exemple, commencer deux instances différentes de VLC.app, en jouant deux fichiers vidéo différents, avec quelque chose comme:

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

puis obtenir les deux processus d'application distincts ids avec, par exemple:

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

Nous pouvons ensuite utiliser Applescript ou Yosemite JXA Javascript pour obtenir une référence à un objet d'application à partir de pid. Il s'avère cependant que quel que soit l'identifiant de processus que nous fournissons, nous recevons toujours une référence à la même instance, exécutant le même fichier vidéo, comme si osascript traduisait simplement un pid en un nom d'application, puis renvoyait toujours le premier processus qui correspond à ce nom.

Yosemite Javascript pour les 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 

Toute réflexion sur une route de script séparément chaque instance?

Répondre

1

Pour chaque cas, demander le nom de la fenêtre de la même ligne que le processus spécifique, comme celui-ci:

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 
+0

Nous pouvons certainement obtenir les propriétés exposées par des événements système comme cela, mais cela ne nous permet toujours pas d'obtenir un objet d'application scriptable pour chacune des instances. Si, par exemple, nous demandons JXA Javascript pour une instance d'application par pid, cela nous donne juste la première instance avec une chaîne de nom correspondante, quel que soit le pid ... – houthakker

+0

A la réflexion, votre approche est un bon moyen de contournant l'objet Application et faisant des scripts d'interface utilisateur ... – houthakker

0

En utilisant l'approche de jackjr300 en Javascript, pour obtenir au moins les scripts de l'interface utilisateur (bien que pas à l'interface de l'objet 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; 
} 
0

JXA est un ensemble de bogues et une conception défectueuse. Son échec à faire des choses comme ça right est déprimant, mais totalement sans surprise (l'équipe AS has form). Comme pour AppleScript, il n'est jamais fourni un moyen direct de cibler les applications par PID. Dans le passé, je l'ai peut-être trompé en activant Apple Remote Events et en ciblant le processus avec une URL eppc://[email protected]/APPNAME?pid=PID, mais en l'essayant tout de suite le 10.10 damned si je pouvais le faire fonctionner car il renvoyait toujours une erreur "remote access not allowed". Appscript a pu faire ce genre de choses pendant son sommeil, mais je l'ai supporté publiquement grâce aux API Cocoa d'Apple d'Apple sur le carbone et le "remplacement" qui l'ont forcé à passer à l'état "hérité".

L'option officiellement prise en charge qui peut fonctionner est le framework Scripting Bridge d'OS X, qui fournit une méthode de ciblage des processus par PID. Bien que comme JXA, il est criblé de défauts de conception, de fonctionnalités manquantes et de problèmes de compatibilité des applications, donc YMWV.

1

Cela semble avoir été corrigé dans El Capitan, car votre code JavaScript fonctionnait correctement sur mon ordinateur.