【问题标题】:Opening multiple windows with Applescript使用 Applescript 打开多个窗口
【发布时间】:2014-04-08 15:06:36
【问题描述】:

我正在尝试编写一个 Applescript 以在不同的屏幕位置打开三个 VLC 窗口。该脚本打开了三个 VLC 实例,但它们一个在另一个之上(使用窗口 1 的位置)。感谢代码帮助:

do shell script "open -n /Applications/Video/VLC.app"
tell application "System Events"
    activate
    set bounds of first window of application "VLC" to {13, 36, 790, 519}
end tell

do shell script "open -n /Applications/Video/VLC.app"
tell application "System Events"
    activate
    set bounds of second window of application "VLC" to {13, 544, 790, 1027}
end tell

do shell script "open -n /Applications/Video/VLC.app"
tell application "System Events"
    activate
    set bounds of third window of application "VLC" to {13, 1043, 790, 1526}
end tell

【问题讨论】:

  • 如果您只创建一个或两个 VLC 实例,然后在一个单独的 Applescript 中将单个窗口大小更改为完全不同的东西,会发生什么情况?那样有用吗?您的 Applecsript 是否真的针对正确的应用程序?
  • 有两个问题。首先,您有三个 VLC 实例,每个实例只有一个窗口。其次,有多个“VLC”应用程序正在运行,因此您无法通过名称来解决它们。您必须通过以下方式获取他们的 pid:tell application "System Events" to set {procesList, pidList} to the {name, unix id} of (every process whose name contains "VLC")

标签: windows shell applescript


【解决方案1】:

@khagler 的评论提供了正确的指针:VLC 实例必须通过 System Events 上下文中的 PID(进程 ID;在 AppleScript 中称为 unix id)来区分。

下面的代码应该做你想做的事,经过大量的辛劳和麻烦 - 与 [AppleScript 障碍] 课程相当。一个障碍是 VLC 实例的主窗口没有立即创建。

cmets 提供了更多细节。

请注意,由于用户界面元素是通过编程方式操作的,因此出于安全原因,必须为运行您的脚本的应用程序授予 assistive access

请注意,我使用 do shell script "open -na VLC.app" 启动实例,这取决于启动服务已知的应用程序的位置(如果由于某种原因不起作用,请恢复为指定完整路径的方法)。

# Specify the desired window bounds.
# !! In the "System Events" context, windows do not 
# !! have `bounds` properties, but separate `position` and
# !! `size` properties.
set WIN_POSITIONS to {{13, 36}, {13, 544}, {13, 1043}}
set WIN_SIZES to {{790, 519}, {790, 519}, {790, 519}}

# Launch the VLC instances.
repeat with i from 1 to count of WIN_POSITIONS
    do shell script "open -na VLC.app"
end repeat

# Note:
# Instance-specific manipulation must
# be performed in the "System Events" context, because
# we must distinguish the VLC instances by their
# PIDs (process IDs; called `unix id` in AppleScript).
tell application "System Events"

    # Get the PIDs (process IDs) of all VLC instances.
    set vlcPids to get the unix id of every process whose name is "VLC"

    # Loop over all instance PIDs.
    # !! It is imperative to *continue* to use object specifiers
    # !! with *filters based on the PID* so as to ensure that the
    # !! individual instances are targeted.
    # !! Attempting to store references to these instances in
    # !! variables fails subtly, as evidenced by the "Events"
    # !! tab in AppleScript editor later showing the non-specific
    # !! process "VLC" of application "System Events" specifiers.
    set winNdx to 1
    repeat with vlcPid in vlcPids

        # WAIT for each instance to create its main window, wich
        # sadly, is not available right away.
        # Once created, position it.
        set haveWin to false
        tell (first process whose unix id is vlcPid)
            repeat with i from 1 to 25 # times out after 25 * .2 == 5 secs.
                if (count of windows of it) > 0 then
                    set haveWin to true
                    tell front window of it
                        # !! In the "System Events" context, windows do not 
                        # !! have `bounds` properties, but separate `position` and
                        # !! `size` properties.
                        set position to item winNdx of WIN_POSITIONS
                        set size to item winNdx of WIN_SIZES
                    end tell
                    exit repeat
                end if
                delay 0.2 # no window yet; sleep some and try again
            end repeat
        end tell
        if not haveWin then error "VLC instance " & vlcPid & " unexpectedly did not create a window within the timeout period."

        set winNdx to winNdx + 1
    end repeat

end tell

如何使用 Finder 进行这项工作:

Targeting Finder 改变方法有两个原因:

  • 只有 一个 Finder 实例。
  • 你不能用open -na Finder.app打开多个窗口;谢天谢地,this answer 展示了如何做到这一点(请参阅那里的 cmets 了解怪癖)。

请注意,以下内容会盲目打开其他 Finder 窗口。

set WIN_POSITIONS to {{13, 36}, {13, 544}, {13, 1043}}
set WIN_SIZES to {{790, 519}, {790, 519}, {790, 519}}

# Sample target locations for the Finder windows.
# Note the use of the "System Events" context to faciliate use of
# POSIX-style *input* paths; note, however, that the paths are
# *stored* as HFS paths so that Finder accepts them.
tell application "System Events"
    set WIN_TARGETS to {¬
        path of desktop folder, ¬
        path of folder "~/Downloads", ¬
        path of folder "/Library/Audio"}
end tell

set winCount to count of WIN_POSITIONS

# Launch the Finder windows.
tell application "Finder"
    # Create the windows in reverse orders.
    repeat with i from winCount to 1 by -1
        set newWin to make new Finder window
        set target of newWin to item i of WIN_TARGETS
    end repeat
end tell

tell application "System Events"

    set i to 1
    repeat with i from 1 to winCount

        tell window i of application process "Finder"
            # !! In the "System Events" context, windows do not 
            # !! have `bounds` properties, but separate `position` and
            # !! `size` properties.
            set position to item i of WIN_POSITIONS
            set size to item i of WIN_SIZES
        end tell

    end repeat

end tell

【讨论】:

  • 谢谢!唯一困扰我的是WIN_TARGETS,如何添加下载目录?或者一些自定义路径..
【解决方案2】:

在搜索了互联网并进行了多次试验和错误之后,我发现如果您允许 AppleScript 编辑器(或自动化程序或您自己的应用程序,无论您使用哪个)在System Preferences > Security & Privacy > Privacy > Accessibility 下控制您的计算机(OS X 10.9 Mavericks )。第一次运行脚本/应用程序时,系统会提示您更改设置。授予访问权限后,您第二次运行脚本/应用程序时,窗口将重新定位。

    do shell script "open -n /Applications/VLC.app /path/to/first/file" --edit path
    do shell script "open -n /Applications/VLC.app /path/to/second/file" --edit path

    delay 3 --wait 3s for VLC to open files, increase if necessary

    tell application "System Events"
        set pidList to the unix id of (every process whose name contains "VLC")

        tell (first process whose unix id is item 1 of pidList)
            set the position of the front window to {0, 22} --edit {x,y}
        end tell

        tell (first process whose unix id is item 2 of pidList)
            set the position of the front window to {640, 22} --edit {x,y}
        end tell
    end tell

它没有mklement0's answer 聪明,但作为 AppleScript 的新手,我可以理解发生了什么。

【讨论】:

  • 我可以看出我的答案是多么不容易理解,但如果您想要 稳健性,则需要它的复杂性:我的答案不依赖于硬编码的延迟(和应用程序)路径)。相信我,我希望不需要这种额外的复杂性,但确实如此。 AppleScript 有很多很多微妙的陷阱。
  • 我看你的剧本越多,我学到的越多,我就越能理解为什么你的答案更好。我正在使用我的快速而肮脏的脚本来打开两个不会改变的网络摄像头流,无论如何我都必须对窗口位置进行硬编码,这样就足以满足我的目的了。
  • 抱歉耽搁了,但最后还是使用了@mklement0 解决方案,效果很好。非常感谢所有不厌其烦地找出解决我问题的方法的人。如果你在英国的阿斯科特附近,我欠你一杯啤酒!!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-22
  • 2018-09-22
  • 2014-10-19
  • 2010-12-20
  • 1970-01-01
  • 2011-07-16
相关资源
最近更新 更多