Why won't my progress bar show?

I’ve got a script that uses Applescript’s built-in progress bar.

If I save the script as an app, run it, progress-bar UI works fine.

But this script is a bit different… it needs to run called from another script, which is on a command key in FastScripts.

The reason it’s run by another script is that the main script accepts an argument that tells it what command key it was run from… it’s a long script that does slightly different things based on which key invoked it.

So it’s called from a script that’s just:

use AppleScript version "2.4" -- Yosemite (10.10) or later
use scripting additions

tell script "Script Additions" to set scriptsPath to POSIX path of get_scripts_folder()
set openOrderScript to (POSIX file (scriptsPath & "Bigger Script.app")) as alias
run script openOrderScript with parameters {1}

The function “get_scripts_folder()” just returns the path the scripts are in.

Then the longer script runs.

When I first tried this, I just changed the longer script that gets called - “Bigger Script.app” here - to a .app, where it has been a .scpt. That didn’t make it display the dialog, so I thought “shoot, it won’t work because it’s still being called by a .scpt.”

So I made the calling script a .app. No luck, still no UI.

If I disable the “on run” handler in the big script and set the incoming argument directly, and run that off FastScripts, the progress dialog UI shows fine. So it’s not just a run-of-the-mill script bug in the big script, it’s either something about the “on run” handler, or, more likely I figure, the fact it’s being called from another script, even though both are .apps.

Any help please?

Thanks in advance,

t.spoon

Thanks, but I don’t think that thread applies to my situation. I’m not having trouble with delays in showing updates in the progress dialog, I am getting no visible progress dialog at all. The task completes successfully without ever showing the dialog.

It’s like when you run an Apple progress bar from Script Debugger, or script Editor, or save it as a .scpt and run it from Fastscripts - you don’t get the UI. To get the UI, you have to save it as an .app and run the app.

But for some reason, if I save it as a .app, and run that .app from another .app then the dialog is not shown.

I’m hoping some veteran who’s deep in the weeds about how this all works might know some trick here. Like

tell me to activate

or that sort of thing, but I’ve tried that and it didn’t help.

Thanks though,

t.spoon

I know before I just referenced this “bigger script” without providing code, because it’s a big mess of code.

So let me distill it down here to what doesn’t work, which is what I should have posted to begin with.

I save this script in my downloads folder as a .app named “Script 2.app”

set theSteps to 10
set progress total steps to theSteps
set progress completed steps to 0
set progress description to "Doing Something..."
set progress additional description to "Preparing to do other things."
repeat with i from 1 to theSteps
	set progress additional description to "Processing item " & i & " of " & theSteps
	set progress completed steps to i
	delay 1
end repeat
set progress total steps to 0
set progress completed steps to 0
set progress description to ""
set progress additional description to ""

Then I also save this script in my downloads folder as a .app named “Script 1.app”

run script ((path to downloads folder as text) & "Script 2.app") as alias

If I double-click to run Script 2.app, the progress dialog shows and works as expected.
If I double-click to run Script 1.app, the script just launches and runs for 10 seconds then exits, without ever showing the dialog at all.

I’d look at switching to Stephen’s SKProgressBar, but this script will be deployed widely on different OS versions, and it appears from what I’ve seen in discussion here that:

  • There’s no one version of SKProgressBar that’s compatible with both the newest and oldest OS versions I need to deploy to
  • SKProgressBar does not like having multiple versions installed simultaneously

Which would make deploying/using it a PITA.

I can just give up and use notifications. Or we already have Shane’s Dialog Toolkit deployed to all users, and although progress dialogs are not an intended use case there, I could probably hack something together to use it instead.

Or I could always make entirely different versions of the script to run off the different command keys, and deal with the fact that the different versions are 99% shared code by putting it all in a shared library.

But I was hoping maybe someone would just have a simple bit of code that fixes my problem.

Well, you do in both those editors – just in a different form. FastScripts doesn’t, but it theoretically could.

But I don’t think its ever going to work via run script. Regardless of the format you save in, run script does the same thing – it loads the code as a script object, and runs it. Those properties only work at the top level of a script, which is where the host looks for them.

For some gory details, see: http://blog.latenightsw.com/?p=836

Try in the Script Editor this script. It calls your other script applet:


set theAppAlias to ((path to downloads folder as text) & "Script 2.app") as alias

tell application "Finder"
	activate
	open theAppAlias
end tell

tell application "Script 2" to quit

I think, instead of opening with parameters, you can get/set properties of applet before opening it with Finder.

Ok, thanks everyone, I think I have a better understanding now.

Per Shane, what I’m doing isn’t going to work. So I need a different route.

Fredrik71 and KniazidisR present the workaround of just invoking the script by launching it as an app, just like any application, which does make the dialog show.

The issue there is that the only reason I’m running it from another script at all is that I pass in information that changes its behavior, and I’m not currently seeing how to do that with these methods.

KniazidisR, you say: “I think, instead of opening with parameters, you can get/set properties of applet before opening it with Finder.”

I’m not familiar with that, can you elaborate? On setting the properties before opening it?

I didn’t know that could be done and I’m interested in how that works. However, while I’d like to learn, I doubt it will work in my unusual environment. The script lives on a Dropbox folder shared with about 4 dozen people or so running it constantly. Calling it with an argument, those users can all get different behaviors based on the command key it was run from, even if 10 people are running it at once. But if I’m actually changing a property value in the script externally and then running it, I’m guessing that multiple users hammering the script simultaneously is going to lead to unexpected behavior in some cases. If it’s even possible in this setup - the Dropbox folder with the script is read-only to most users, so they probably can’t modify the properties.

Still, I’m curious to learn how this would work.

So, at this point it seems best to stop calling the same script via different scripts from different command keys and passing in the information about which script called it, and just rewrite the thing to put the very large amount of shared code into a library, split it into different scripts, which run directly off the command keys.

Thanks everyone,

t.spoon.

Thanks Fredrik71, I am interested in ways to call an Applescript and pass information into it other than using “run script [some script] with parameters {x}”

If I understand correctly, that’s probably right. But…

You can pass launch arguments like this:

use framework "Foundation"
use framework "AppKit"
use scripting additions

set thePath to "~/Desktop/Test App.app"
set thePath to (current application's NSString's stringWithString:thePath)'s stringByExpandingTildeInPath()
set theURL to (current application's NSURL's fileURLWithPath:thePath)
set argDict to current application's NSDictionary's dictionaryWithObject:{"-blahBlah", "Hello world"} forKey:(current application's NSWorkspaceLaunchConfigurationArguments)
set ws to current application's NSWorkspace's sharedWorkspace()
ws's launchApplicationAtURL:theURL options:(current application's NSWorkspaceLaunchDefault) configuration:argDict |error|:(missing value)

And handle them like this:

use framework "Foundation"
use framework "AppKit"
use scripting additions

on run
	set x to (current application's NSUserDefaults's standardUserDefaults()'s objectForKey:"blahBlah")
	if x is not missing value then
		my blahBlah:(x as text)
	end if
end run

on blahBlah:x
	display dialog x
end blahBlah:

Hi, spoon. I was at work.

The Shane already shown you how to change the outer script’s properties. But as I read then above you want the outer script to be read/only for the users. So, here is workaround how to take different behaviour for different users (that is, providing parameters):

Save you Script 2.app as this:


on showProgressBar(userName)
	
	set theSteps to 10
	set progress total steps to theSteps
	set progress completed steps to 0
	set progress description to "Doing Something for " & userName
	set progress additional description to "Preparing to do other things."
	repeat with i from 1 to theSteps
		set progress additional description to "Processing item " & i & " of " & theSteps
		set progress completed steps to i
		delay 1
	end repeat
	set progress total steps to 0
	set progress completed steps to 0
	set progress description to ""
	set progress additional description to ""

end showProgressBar

Run Script 1 as this (providing user name):


set theAppAlias to ((path to downloads folder as text) & "Script 2.app") as alias

set outerScript to load script theAppAlias
set userName to "KniazidisR" -- test with other user names too

return outerScript's showProgressBar(userName)

Actually, this is simpler and probably more useful:

	set theArgs to current application's NSProcessInfo's processInfo()'s arguments() as list

Big thanks to all of you, Fredrik71, Shane, and KniazidisR. All your suggestions are useful and helped me learn.

I’d already gone the simple route - I stopped having the command keys run a script that called another script with different arguments, and just made the command keys each directly run a .app script that included the progress dialog code, with the shared code in a new library.

That’s usually how I’d go about things, it’s just that this script looks like:

[do a bunch of things, set a bunch of variables, all the same regardless of the calling command key]
[do one tiny thing different based on the calling command key]
[do a bunch more stuff using a bunch of the variables set earlier, that’s all the same regardless of the calling command key]

With that sort of structure, just having it be one script where the small differences in behavior were invoked by the different arguments being passed based on the command key made sense.

It looks to me like all your workarounds would work, but by the time I got there, I’d already gone ahead and forgot about a calling script / argument passing, and just made it two separate .apps, each called directly, sharing code via a library. Which finally made the UI show.

I’m sure Shane probably understands, but I don’t understand why something like “Display dialog” works perfectly fine in almost every situation, but displaying progress hides anytime you do anything in the most slightly different way.

Look in the Variables list in Script Debugger, where it shows AppleScript. Expand it to show AppleScript’s properties, and you’ll see that progress description et al are just properties, much the same as text item delimiters.

Save this script on your desktop as Delims.scpt:

set text item delimiters to {"blah blah blah"}

Now tell me what you expect when you run this script:

set deskPath to path to desktop as text
set theScript to (deskPath & "Delims.scpt") as alias
run script theScript
return {"one", "two"} as text