How to create a simple "Please wait..." message?

Over the year, various posts in this forum have offered ways to display a simple “Please wait…” message while other AppleScript commands continue to run in the background. Some of these used the application “AppleScript Runner” or “Automator Runner” - but, as far as I can tell, neither of these exist in recent macOS versions.

Is there a simple way to create such a message? The best I can come up with (and I’m a complete beginner at this kind of thing) is this. First, create a script application called PleaseWait.app, with at least this code:

display dialog "Please wait ..." with title "Working" buttons {"OK"}
error number -128

Then create a testing script application, with the PleaseWait.app stored inside it, in a Contents:Helpers folder. The script for the application looks like this - and the lines that open Microsoft Word are only there as an EXAMPLE of commands that run in the background while the Please Wait message continues to be visible:

use scripting additions

set myPath to POSIX path of (path to me)
set pleaseWait to myPath & "Contents/Helpers/PleaseWait.app"
do shell script "open" & space & quoted form of pleaseWait

-- this is here only as an EXAMPLE of what might happen in the background! It's only an example!
tell application "Microsoft Word"
	activate
	quit
end tell
-- remember that the above four lines are only an EXAMPLE!

tell application "System Events"
	set pwID to (unix id of processes whose name is "PleaseWait")
	try
		do shell script "kill -9 " & pwID
	end try
end tell

There must be a better way than this, and I’ll be grateful for any suggestions about what it might be.

How about this? It uses my Custom Notification script idea. The advantage is you can adjust the notification as want. You can edit its window dimensions, position on the screen, font of the message inside the window, the time notification appears, the time it closes and so on.


use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "AppKit"
property wController : missing value -- outlet equivalent in AsObjC
property notificationTitle : "Working"
property aWidth : 300
property aHeight : 60
property notificationText : "
    Please wait ..."

my performSelectorOnMainThread:"displayNotification:" withObject:({aWidth, aHeight, notificationTitle, current application's NSString's stringWithString:notificationText}) waitUntilDone:true

-- this is here only as an EXAMPLE of what might happen in the background! It's only an example!
repeat with i from 5 to 1 by -1
	say i
	delay 1
end repeat
say "Start"
-- remember that the above 5 lines are only an EXAMPLE!

my closeNotification()


------------------------------------ HANDLERS ------------------------------------------------
on displayNotification:paramObj
	copy paramObj to {aWidth, aHeight, aTitle, notificationText}
	set aColor to current application's NSColor's colorWithDeviceRed:0.0 green:0.0 blue:0.0 alpha:0.9
	set aView to current application's NSTextView's alloc()'s initWithFrame:(current application's NSMakeRect(0, 0, aWidth, aHeight))
	aView's setRichText:true
	aView's useAllLigatures:true
	aView's setTextColor:(current application's NSColor's cyanColor()) --
	aView's setBackgroundColor:aColor
	aView's setEditable:false
	aView's setFont:(current application's NSFont's fontWithName:"Menlo" |size|:20)
	set aScreen to current application's NSScreen's mainScreen()
	set aFrame to {{0, 0}, {aWidth, aHeight}}
	set aBacking to current application's NSTitledWindowMask
	set aDefer to current application's NSBackingStoreBuffered
	set aWin to current application's NSWindow's alloc()
	(aWin's initWithContentRect:aFrame styleMask:aBacking backing:aDefer defer:false screen:aScreen)
	aWin's setTitle:aTitle
	aWin's setDelegate:me
	aWin's setDisplaysWhenScreenProfileChanges:true
	aWin's setHasShadow:true
	aWin's setIgnoresMouseEvents:false
	aWin's setLevel:(current application's NSNormalWindowLevel)
	aWin's setOpaque:false
	aWin's setAlphaValue:0.9 --append
	aWin's setReleasedWhenClosed:true
	aWin's |center|()
	aWin's setContentView:aView
	aView's setString:notificationText
	set my wController to current application's NSWindowController's alloc()
	my (wController's initWithWindow:aWin)
	my (wController's showWindow:me)
end displayNotification:

on closeNotification()
	my wController's |close|()
end closeNotification

@KniazidisR - That’s perfect! Thank you! Is there a site where more of your sample code is posted?

Thank you again!

Four years later, I asked Claude Code to solve this problem, and it came up with a simple and reliable answer (after a few failed attempts, which it fixed when prompted to do so). Here’s a sample app:

-- Please Wait dialog by Claude Code
-- 16 May 2026

use AppleScript version "2.4"
use scripting additions

on run
	set waitID to showPleaseWait("Testing…")
	delay 5
	dismissPleaseWait(waitID)
end run

on showPleaseWait(theMessage)
	set inner to "display dialog \"" & theMessage & ¬
		"\" buttons {\"Hide\"} default button 1" & ¬
		" with title \"Please Wait\" with icon note" & ¬
		" giving up after 86400"
	set cmd to "/usr/bin/osascript" & ¬
		" -e 'tell application \"System Events\" to activate'" & ¬
		" -e " & quoted form of inner & ¬
		" </dev/null >/dev/null 2>&1 & echo $!"
	return (do shell script cmd)
end showPleaseWait

on dismissPleaseWait(waitID)
	try
		do shell script "kill " & waitID
	end try
end dismissPleaseWait

I don’t think SKProgressBar is downloadable from anywhere. Were you able to find a location for it?

It is.

SKProgressBar2.0

Aha! Excellent! Thank you!

Despite not understand a lick of Cocoa, I shamelessly ‘adapted’ this into a subscript to avoid the notorious file spec bug and it worked. Until I got ambitious and tried to regularly update the text field in the window without opening and closing a new window. I suspect that later approach will excessively thrash memory. How do I reset that “aView’s setString:notificationText” component?

Strict no giggling policy, please.

Have appended another handy trick as advanced payment.

Code follows below:

use AppleScript version "2.4"
use scripting additions

property aController : missing value -- outlet equivalent in AsObjC

set shortlist1 to "▶︎Time 1" & return & " Time 2" & return & " Time3"
set shortlist2 to " Time 1" & return & "▶︎Time 2" & return & " Time3"
set shortlist3 to " Time 1" & return & " Time 2" & return & "▶︎Time3"

set aController to DisplayNotificationWindow("Playing Clipboard Times", shortlist1, 650, 450, aController)
delay 1
closeNotification(aController)
set aController to DisplayNotificationWindow("Playing Clipboard Times", shortlist2, 650, 450, aController)
delay 1
closeNotification(aController)
set aController to DisplayNotificationWindow("Playing Clipboard Times", shortlist3, 650, 450, aController)
delay 1
closeNotification(aController)

try
	set aController to DisplayNotificationWindow("Playing Clipboard Times", shortlist1, 650, 450, aController)
	delay 2
	set aController to DisplayNotificationWindow("", shortlist2, 650, 450, aController)
	delay 2
	set aController to DisplayNotificationWindow("", shortlist3, 650, 450, aController)
	delay 2
	closeNotification(aController)
on error errorMssg number errorNumber
	log errorMssg & "#" & errorNumber
	closeNotification(aController)
end try


-- handlers using Foundation and Appkit must be individually wrapped like this because of a bug that damages file references and script-loading in the main code
-- this handler combines two code stubs on modeless message windows and script wrappers that evade nasty ' Use framework "Foundation" ' bugs
-- Now I just need a scroll bar and some .rtf output and I'll be cooking with real gas, as they say...
on DisplayNotificationWindow(NTitle, nText, Nx, NY, CloseController)
	script theScript
		property parent : a reference to current application
		property wController : missing value -- outlet equivalent in AsObjC
		property notificationTitle : "" -- only needed for displayNotification
		property notificationText : "" -- only needed for displayNotification
		property aWidth : 300 -- only needed for displayNotification
		property aHeight : 60 -- only needed for displayNotification
		use framework "Foundation"
		use framework "AppKit"
		on DisplayNotificationWindow(NTitle, nText, Nx, NY, CloseController)
			if (NTitle is "") and (nText is "") then
				tell me to CloseController's |close|() -- finding this exact construction drove me batty
			else if NTitle is "" then
				-- •• I want to update the window's contents to 'nText' without thrashing memory
				-- by closing and opening a new window but I can't figure out what goes here...
				
			else
				set {notificationTitle, notificationText, aWidth, aHeight} to {NTitle, nText, Nx, NY}
				my performSelectorOnMainThread:"displayNotification:" withObject:({aWidth, aHeight, notificationTitle, current application's NSString's stringWithString:notificationText}) waitUntilDone:true
			end if
			return wController
		end DisplayNotificationWindow
		
		on displayNotification:paramObj
			copy paramObj to {aWidth, aHeight, aTitle, notificationText}
			set aColor to current application's NSColor's colorWithDeviceRed:1 green:1 blue:1 alpha:1 -- white
			set aView to current application's NSTextView's alloc()'s initWithFrame:(current application's NSMakeRect(0, 0, aWidth, aHeight))
			aView's setRichText:true
			aView's useAllLigatures:true
			aView's setTextColor:(current application's NSColor's blackColor())
			aView's setBackgroundColor:aColor
			aView's setEditable:false
			aView's setFont:(current application's NSFont's fontWithName:"Courier" |size|:14)
			set aScreen to current application's NSScreen's mainScreen()
			set aFrame to {{0, 0}, {aWidth, aHeight}}
			set aBacking to current application's NSTitledWindowMask
			set aDefer to current application's NSBackingStoreBuffered
			set aWin to current application's NSWindow's alloc()
			(aWin's initWithContentRect:aFrame styleMask:aBacking backing:aDefer defer:false screen:aScreen)
			aWin's setTitle:aTitle
			aWin's setDelegate:me
			aWin's setDisplaysWhenScreenProfileChanges:true
			aWin's setHasShadow:true
			aWin's setIgnoresMouseEvents:false
			aWin's setLevel:(current application's NSNormalWindowLevel)
			aWin's setOpaque:false
			aWin's setAlphaValue:0.9 -- append to 1.0 for opaque
			aWin's setReleasedWhenClosed:true
			aWin's |center|()
			aWin's setContentView:aView
			aView's setString:notificationText -- < I need to alter this field without closing/opening a new window
			set my wController to current application's NSWindowController's alloc()
			my (wController's initWithWindow:aWin)
			my (wController's showWindow:me)
		end displayNotification:
		
	end script
	return theScript's DisplayNotificationWindow(NTitle, nText, Nx, NY, CloseController)
end DisplayNotificationWindow

on ReadKeyPress(whichKey)
	script theScript4
		property parent : a reference to current application
		use framework "Cocoa"
		on ReadKeyPress(whichKey)
			if whichKey begins with "opt" then
				return isKeyPressed(current application's NSEventModifierFlagOption)
			else if whichKey begins with "cap" then
				return isKeyPressed(current application's NSEventModifierFlagCapsLock)
			else if (whichKey begins with "shi") or (whichKey begins with "sft") then
				return isKeyPressed(current application's NSEventModifierFlagShift)
			else if (whichKey begins with "con") or (whichKey begins with "ctl") or (whichKey begins with "ctrl") then
				return isKeyPressed(current application's NSEventModifierFlagControl)
			else if whichKey begins with "com" then
				return isKeyPressed(current application's NSEventModifierFlagCommand)
			else if whichKey begins with "help" then
				return isKeyPressed(current application's NSEventModifierFlagHelp)
			end if
		end ReadKeyPress
		to isKeyPressed(ParameterFlag)
			((current application's NSEvent's modifierFlags()) / (ParameterFlag) as integer) mod 2 is equal to 1
		end isKeyPressed
	end script
	return theScript4's ReadKeyPress(whichKey)
end ReadKeyPress

Apologies. I left out this very necessary piece of code:

on closeNotification(theController)
my DisplayNotificationWindow(“”, “”, 0, 0, theController)
end closeNotification