2

I am new to Cocoa and AppleScript. Recently I want to do something via the "do shell script" command in Cocoa-AppleScript many times, and show a window with a progress bar at the same time to indicate how many times I've done.

My code looks like this:

property progressBar: missing value
on applicationWillFinishLaunching_(aNotification)
    repeat with i from 1 to 8
        set progressBar's doublevalue to i
        do shell script "sleep 1"
        delay 1
    end repeat
end applicationWillFinishLaunching_

This will show up a progress bar and indicates the progress. However, the window that contains the progress bar will be inactive until the repetition is finished. I think this is because the Cocoa-AppleScript app have only one thread so when it's doing the "do shell script" command the GUI just cannot handle other events. I tried to let the shellscript run in background with a tailed "&", but it behaves like hanged and still consumes a lot of time.

I think even the "do shell script" command can be done in the background I still need to be notified when it's finished to update the progress bar, but I don't know how to achieve that.

So my question is: How to do something via "do shell script" asynchronously, and be informed when the job is finished, in Cocoa-AppleScript?

(By the way, if I remove that "delay 1" line, the progress bar will not even update, does anyone know the reason?)

  • 1
    You are right about the single thread issue, which can be a problem when trying to do this type of thing with Applescript. There are 'wrapper' applications, (one comes to mind called "[Platypus](http://www.sveinbjorn.org/platypus)") that might be able to do what you're wanting, so maybe consider that as an option. – l'L'l Apr 20 '16 at 04:33
  • @l'L'l I will try to use this app. Thank you! – Ping Fang Chiang Apr 20 '16 at 07:58

1 Answers1

0

Use NSTask. You'll need to use a few lines of ObjC to define a completion handler that calls back into your AS code as ASOC doesn't support blocks itself, but otherwise it does exactly what you need.

foo
  • 3,171
  • 17
  • 18
  • Actually the reason why I chose to use AppleScript to do this is that I don't want to learn ObjC at all... Still, thank you for the help. :) – Ping Fang Chiang Apr 20 '16 at 15:06
  • 1
    If you want to run a subprocess asynchronously _and_ get a completion notification, use `NSTask`. Yes, the lack of blocks support in ASOC is famously annoying, but it's not insurmountable. The reason using `do shell script` with `&` doesn't return immediately is that the subprocess's stdout and stderr pipes are still connected to your process; however, if you redirect those then your process no longer receives any feedback. No doubt there are crazy ways you could kludge it, but you're just tying yourself in knots and potentially creating all sorts of nasty gotchas. Simpler just to use ObjC. – foo Apr 20 '16 at 20:21
  • Or, assuming you're not doing any application scripting, which is the one thing AppleScript does do right, you could just forget about using AppleScript entirely, suck it up, and go learn Swift instead. At least with Swift you'll get a large, knowledgeable user community, extensive tool and documentation support, and a well supported language that isn't hopelessly moribund, even if the damn thing is stupidly overcomplicated and still buggy as anthills. But eh, it's the Future. – foo Apr 20 '16 at 20:31
  • I've learned Swift for a while. Although it is buggy, annoying with some features as well as its poor IDE (xcode), for me it's still much more understandable than the ObjC. That's another reason that I don't want to spend time learning ObjC. But this project I'm writing is supposed to support OS version to OS X 10.7, on which Swift is unavailable. Thus came this AppleScript question... – Ping Fang Chiang Apr 21 '16 at 07:56