如何通过osascript处理同一应用程序的两个实例
How can one address two instances of the same application through osascript
有人能想出一个解决方案来解决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应用程序:
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
对分别为每个实例编写脚本的方法有什么想法吗?
对于每个实例,从与特定进程相同的行中询问窗口的名称,如下所示:
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
这在El Capitan中似乎已经修复,因为您的JavaScript代码在我的机器上运行良好。
在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;
}
JXA是一堆错误和有缺陷的设计。它没能做到这一点令人沮丧,但完全不足为奇(AS团队有状态)。
至于AppleScript,它从未提供过通过PID直接定位应用程序的方法。在过去,我可能通过启用远程Apple事件并使用eppc://USER@HOST/APPNAME?pid=PID
URL定位进程来欺骗它,但现在在10.10上尝试它,如果我能让它工作的话,那就该死了,因为它总是返回"不允许远程访问"错误。
Appscript可以在睡眠中完成这项工作,但我放弃了公众对它的支持,因为苹果的碳战争和糟糕的"替代"Cocoa API迫使它进入"遗留"状态,所以你在那里只能靠自己了。
官方支持的一个可行的选项是OSX的ScriptingBridge框架,它提供了一种通过PID确定进程目标的方法。尽管和JXA一样,YMWV也充满了设计缺陷、功能缺失和应用程序兼容性问题。
- 当同一浏览器的两个实例浏览时,Javascript页面如何具有唯一的ID
- 如何通过osascript处理同一应用程序的两个实例
- Backbone relational无法实例化两个RelationalModel对象
- 在两台不同的服务器上运行同一node.js应用程序的两个实例
- 一个用户脚本的两个实例如何在帧之间进行通信
- Colorbox插件正在加载其自身的两个实例
- javascript中的Ruby插值在两个实例中的一个实例中不起作用
- 当有两个浏览器实例时,如何检查浏览器会话是否存在
- Browserify:如何 aviod 两个 jQuery 实例
- 防止在 NodeJS 中同时运行两个函数实例
- 比较两个组件 - 组件 X 是组件 A 的实例吗?
- 使用 jQuery 创建两个日期选取器日期范围实例
- Javascript — 相同元素的两个实例
- 两个实例包含相同的值
- 如何更新表示相同数据的两个不同React组件实例
- 如何从两个jquery:contains()选择器实例中获取总实例
- 不能使用ezinearticles作者小部件的两个实例
- Widget的两个实例只有一个实例在工作
- 删除角色的最后两个实例
- 一个指令的两个实例正在使用同一个模板实例