How to run a loop only once when an application is activated?

Hello everyone,

I am quite new to Apple scripting.

What I am trying to build is a script that shows a reminder alert to user every time he/she switched to a certain app from another app.

Let’s say customer is running Safari, Pages, and Notes at the same time and currently using Safari.

I want to show an alert once he/she switches to Notes app asking whether they read some disclaimer or not.

However, for each switch to Notes app I want this to be displayed once. Regardless from which answer is provided.

If customer finished their work with Notes app, and then returns back to Safari this should be running in the background so that if they switch to Notes again alert will be displayed again.

I have managed to make it run upon activation but I could not manage to run it only once for each switch back and how to keep it running in the background

Below what I have so far:

property stop_loop : false
on run
	tell application "System Events"
		set ProcessList to name of every process
		repeat while "notes" is in ProcessList
			tell application "System Events"
				set activeApp to name of first application process whose frontmost is true
				if "notes" is in activeApp then
					repeat until stop_loop = true
						display alert "This is an alert" buttons {"Did not read", "I have already read"}
						if button returned of result = "Did not read" then
							display alert "You have to read the disclaimer"
							if button returned of result is "OK" then set stop_loop to true
						else
							if button returned of result = "I have already read" then
								display alert "Continue"
								if button returned of result is "OK" then set stop_loop to true
							end if
						end if
					end repeat
				end if
			end tell
			delay 0.5
		end repeat
	end tell
end run

I will really appreciate for your help.

You should save the following script as stay-open application:


on idle {}
	tell application "System Events" to set ProcessList to every application process
	repeat with aProcess in ProcessList
		if name of aProcess is "Notes" then
			if frontmost of aProcess then
				display notification "The process  " & (name of aProcess) & " is frontmost"
			end if
			-- do HERE your display dialogs, or other stuff
			exit repeat -- exit from loop immediately
		end if
		delay 1
	end repeat
end idle

Then run your stay-open application instead of the script. Read more about 2 things:

  1. what is on idle{} handler.
  2. what does exit repeat command.

Now, I go at work.

Hello @KniazidisR,

Thank you so much for your response.

However, after running your script I am not sure whether I explained my goal properly or not.

So please let me try again.

I want my script runs as a stay open application (thank you for leading me on this).

Regardless of how many applications is being actively used by current user, I want that user too see an alert when they switched to Notes (i.e. makes it active/frontmost application): “Did you read the disclaimer?” with 2 buttons “Yes I did” and “No I did not”.

If user clicks to “Yes I did” then another dialog should appear saying “Thank you. You may now continue to your work with Notes” with an "OK button. If he/she clicks “OK” then dialog disappears so that they can continue working on Notes.

If user clicks “No I did not” then another dialog should appear saying “You have to read the disclaimer first!” with an "OK button. If he/she clicks “OK” then dialog disappears so that they can continue working on Notes.

After he/she finishes current work on Notes and then switches to (Let’s say) Safari. This app will be running in the back ground.

I want exact same alert and dialog process to be seen again once they switch back to Notes.

I modified your script as you described as below. However it simply does not show alert when I switched to Notes app and started to write something. Instead it shows what I want when I switched back to another app and wait for a while.

on idle {}
	tell application "System Events" to set ProcessList to every application process
	repeat with aProcess in ProcessList
		if name of aProcess is "Notes" then
			if frontmost of aProcess then
				display notification "The process  " & (name of aProcess) & " is frontmost"
			end if
			display alert "Did you read the disclaimer?" buttons {"No I did not", "Yes I did"}
			if button returned of result = "No I did not" then
				display alert "You have to read the disclaimer first!"
			else
				if button returned of result = "Yes I did" then
					display alert "Thank you. You may now continue to your work with Notes"
				end if
			end if
			exit repeat
		end if
		delay 0.5
	end repeat
end idle

Looking forward to your and also other experienced scripters’ response.

I made some mistakes in the previous script. The most important mistake was returning the delay. The correct script:


property NotesIsFrontmost : false

on idle {}
	tell application "System Events"
		if application process "Notes" exists then
			tell application process "Notes"
				
				if frontmost then
					if NotesIsFrontmost is false then
						set NotesIsFrontmost to true
						display notification "Process \"Notes\" has become frontmost right now!"
						if button returned of (display alert "Did you read the disclaimer?" buttons {"No I did not", "Yes I did"}) is "No I did not" then
							display alert "You have to read the disclaimer first!"
						else
							display alert "Thank you. You may now continue to your work with Notes"
						end if
					end if
				else
					set NotesIsFrontmost to false
				end if
				
			end tell
		end if
	end tell
	return 1
end idle

Hello again @KniazidisR,

Thank you so much for your response.

Your last script works exactly as expected.

I tried multiple runs with no issue.

Thank you again.