【问题标题】:Progress Bar in Applescript windowApplescript 窗口中的进度条
【发布时间】:2020-04-14 07:23:17
【问题描述】:

我想在 macOS 上使用 bash 脚本下载不同的应用程序。

由于有一些较大的下载(例如 Office 365),我想在常规 macOS 窗口中包含一个进度条。

应用程序下载+安装脚本如下所示

cd ~/Downloads/ && { curl -O https://dl.google.com/chrome/mac/stable/GGRO/googlechrome.dmg ; cd -; }
sudo hdiutil attach ~/Downloads/googlechrome.dmg
sudo cp -r /Volumes/Google\ Chrome/Google\ Chrome.app /Applications/
diskutil unmount Google\ Chrome

但这不会为用户显示任何进度(脚本将在后台运行)。

我找到了以下示例并根据自己的喜好对其进行了一些编辑

chromedl() {
    osascript <<AppleScript
    set progress description to "Loading"
set progress additional description to "Please wait"
set progress total steps to 3
repeat with i from 1 to 4
   set theSourceCode to do shell script "curl -L -m 30 seconds [url=https://dl.google.com/chrome/mac/stable/GGRO/googlechrome.dmg]https://dl.google.com/chrome/mac/stable/GGRO/googlechrome.dmg]"
   set progress completed steps to i
end repeat
display dialog "Progress bar is complete."
AppleScript

但这会导致 curl 执行错误。

请帮助我使用正常的 Curl 下载 + 进度条脚本

【问题讨论】:

  • AppleScript 不知道 shell 脚本的进度 - 您如何从下载中获取值,例如总大小和当前大小,以与进度指示器一起使用?还是您只是在寻找一个不确定的指标(微调器)?
  • @red_menace 进度条是理想的,但微调器也是一种解决方案。我只是希望用户有一些视觉反馈表明脚本正在运行。

标签: bash macos shell applescript osascript


【解决方案1】:

使用 AppleScriptObjectiveC 创建一个基本的进度微调器窗口很容易。将以下内容复制到 Script Editor 并在前台运行(command-control-R,或使用菜单命令 Script→Run in Foreground,按住 control 键会出现)。

use framework "AppKit"
use AppleScript version "2.4" -- Yosemite 10.10 or later required
use scripting additions

-- convenience properties to make ASOC more readable
property ca : current application
property NSPanel : class "NSPanel"
property NSView : class "NSView"
property NSProgressIndicator : class "NSProgressIndicator"
property NSTextField : class "NSTextField"

property HUD_mask : 8192
property nonactivating_mask : 128

global progress_panel, progress_indicator, label_field

make_progress_panel()
progress_indicator's startAnimation:me
progress_panel's orderFront:me

-- just hang it out there for 5 seconds as proof of concept
delay 5

progress_panel's |close|()

on make_progress_panel()
    -- make floating panel
    set content_rect to ca's NSMakeRect(200, 800, 140, 80)
    set progress_panel to NSPanel's alloc's initWithContentRect:content_rect styleMask:(HUD_mask + nonactivating_mask) backing:(ca's NSBackingStoreBuffered) defer:true
    set progress_panel's floatingPanel to true

    -- make progress indicator
    set progress_rect to ca's NSMakeRect(0, 0, 40, 40)
    set progress_indicator to NSProgressIndicator's alloc's initWithFrame:progress_rect
    set progress_indicator's indeterminate to true
    set progress_indicator's |style| to 1
    set progress_indicator's translatesAutoresizingMaskIntoConstraints to false

    --make text field
    set label_field to NSTextField's labelWithString:"Downloading"
    set label_field's translatesAutoresizingMaskIntoConstraints to false

    -- make container view, and add subviews
    set content_view to NSView's alloc's initWithFrame:content_rect
    content_view's addSubview:label_field
    content_view's addSubview:progress_indicator
    progress_indicator's sizeToFit()

    set progress_panel's contentView to content_view

    -- view constraints, for alignment
    set pi_y_centering to progress_indicator's centerYAnchor's constraintEqualToAnchor:(content_view's centerYAnchor)
    set lf_y_centering to label_field's centerYAnchor's constraintEqualToAnchor:(content_view's centerYAnchor)
    pi_y_centering's setActive:true
    lf_y_centering's setActive:true

    set lf_left_margin to content_view's leadingAnchor's constraintEqualToAnchor:(label_field's leadingAnchor) |constant|:-10
    lf_left_margin's setActive:true

    set pi_left_margin to label_field's trailingAnchor's constraintEqualToAnchor:(progress_indicator's leadingAnchor) |constant|:-10
    pi_left_margin's setActive:true

    set pi_right_margin to progress_indicator's trailingAnchor's constraintGreaterThanOrEqualToAnchor:(content_view's trailingAnchor) |constant|:10
    pi_left_margin's setActive:true
end make_progress_panel

我认为,使用curl 进行这项工作的最简单方法是完全分离 curl 进程并恢复其 pid,就像这样(最后的代码分离进程并将输出发送到遗忘,然后返回PID):

set curl_pid to do shell script "curl -L [url=...] &> /dev/null & echo $!"

获得 pid 后,您可以设置循环(或空闲处理程序,如果您创建应用程序)并定期检查进程是否仍处于活动状态:

try
    set b to do shell script "pgrep curl | grep " & curl_pid
on error
    progress_indicator's stopAnimation:me
    progress_panel's |close|()
end try

如果您想要一个确定的进度条,这很容易管理,但您必须想办法衡量进度。 This link 建议您可以先获取文件的标题并提取文件大小;随着下载的进行,您可以将其与实际的磁盘文件大小进行比较,并将比率输入进度条。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-23
    • 1970-01-01
    • 2014-09-23
    相关资源
    最近更新 更多