For older macOS versions when
swiftDialog
isn’t an option, leverage Jamf Helper to provide your users actionable messages
Background
For computers running macOS Big Sur 11 or later, swiftDialog
is our go-to tool for displaying end-user messages.
For the less than double-digit stragglers we still have running macOS Catalina, a fresh deployment of Nudge-Python seemed overkill, so we turned to our old friend jamfHelper
and added some new racing stripes:
- Auto-terminate
fullscreen
mode (after a configurable duration) - Auto-execute the specified
action
(when infullscreen
mode)
Introduction
The “official” documentation for Jamf Helper is quite brief:
Jamf Helper
The Jamf Helper (
jamfHelper.app
) displays messages to users. It is stored in the following location on enrolled computers:Jamf Pro Documentation, Overview of Technologies, Applications and Utilities
/Library/Application Support/JAMF/bin/jamfHelper.app
Luckily, the JAMF Helper Help Page fills in the gaps:
/Library/Application\ Support/JAMF/bin/jamfHelper.app/Contents/MacOS/jamfHelper -help
Configuration
Complete the following steps to display actionable messages to your users with Jamf Helper.
A. Conduct a dry-run of the Actionable message with Jamf Helper script
Complete the following steps on an enrolled, testing Mac.
- Open the macOS Terminal.
- Download the latest production version of the Actionable message with Jamf Helper script using the following command. (The script will be saved to your Downloads folder as
Actionable-message-with-Jamf-Helper-reference.bash
):
curl -o ~/Downloads/Actionable-message-with-Jamf-Helper-reference.bash https://raw.githubusercontent.com/dan-snelson/Jamf-Pro-Scripts/master/Jamf%20Helper/Actionable-message-with-Jamf-Helper.bash
- Execute the Actionable message with Jamf Helper script (with elevated privileges) using the following command:
sudo bash ~/Downloads/Actionable-message-with-Jamf-Helper-reference.bash
- Review the dialog’s various parameters:
- Window Type [Parameter 4]
- Icon [Parameter 5]
- Title [Parameter 6]
- Heading [Parameter 7]
- Description [Parameter 8]
- Button 1 (i.e., Default) [Parameter 9]
- Button 2 (i.e., Cancel) [Parameter 10]
- Action [Parameter 11]
- Click Button1 [P9] (i.e., Default) and observe that Digital Color Meter launches, then review the output in Terminal
sudo bash ~/Downloads/Actionable-message-with-Jamf-Helper-reference.bash Caffeinating this script (PID: 18585) 2023-01-17 19:58:32 - ### # Display Message with Jamf Helper and Action (1.4.0) ### 2023-01-17 19:58:32 - The following message will be displayed to the end-user: 2023-01-17 19:58:32 - Title [Parameter 6] Heading [Parameter 7] Description [Parameter 8] goes here, which can be as long as needed. 'fullScreenTimeout' is currently set to '30' seconds Button1 [P9] /System/Applications/Utilities/Digital Color Meter.app 2023-01-17 19:58:35 - Result of user's interaction: 0 2023-01-17 19:58:35 - Open /System/Applications/Utilities/Digital Color Meter.app ... 2023-01-17 19:58:35 - Title [Parameter 6] Heading [Parameter 7] Description [Parameter 8] goes here, which can be as long as needed. 'fullScreenTimeout' is currently set to '30' seconds Button1 [P9] /System/Applications/Utilities/Digital Color Meter.app 2023-01-17 19:58:36 - De-caffeinate … 2023-01-17 19:58:36 - Attempting to terminate the 'caffeinate' process … 2023-01-17 19:58:36 - (Termination message indicates success.) /Users/dan/Downloads/Actionable-message-with-Jamf-Helper-reference.bash: line 110: 18587 Terminated: 15 caffeinate -dimsu -w $$ 2023-01-17 19:58:36 - Goodbye!
- Quit Digital Color Meter and repeat the most recent Terminal command by pressing the up arrow once then pressing Return
- This time, click Button2 [P10] (i.e., Cancel) and confirm Digital Color Meter does not launch, then review the output in Terminal
sudo bash ~/Downloads/Actionable-message-with-Jamf-Helper-reference.bash Caffeinating this script (PID: 18637) 2023-01-17 19:59:24 - ### # Display Message with Jamf Helper and Action (1.4.0) ### 2023-01-17 19:59:24 - The following message will be displayed to the end-user: 2023-01-17 19:59:24 - Title [Parameter 6] Heading [Parameter 7] Description [Parameter 8] goes here, which can be as long as needed. 'fullScreenTimeout' is currently set to '30' seconds Button1 [P9] /System/Applications/Utilities/Digital Color Meter.app 2023-01-17 19:59:28 - Result of user's interaction: 2 2023-01-17 19:59:28 - dan cancelled. 2023-01-17 19:59:28 - De-caffeinate … 2023-01-17 19:59:28 - Attempting to terminate the 'caffeinate' process … 2023-01-17 19:59:28 - (Termination message indicates success.) /Users/dan/Downloads/Actionable-message-with-Jamf-Helper-reference.bash: line 110: 18639 Terminated: 15 caffeinate -dimsu -w $$ 2023-01-17 19:59:28 - Goodbye!
- Use your favorite editor to modify the following lines of
~/Downloads/Actionable-message-with-Jamf-Helper-reference.bash
- Line 78: Change the value of the
fullScreenTimeout
variable from30
to17
- Line 79: Change the value of the
windowType
variable fromhud
tofullscreen
- Line 78: Change the value of the
Note: If you observe a warning about unusual line terminators, click Ignore
#################################################################################################### # # Variables # #################################################################################################### # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Script Version and Jamf Pro Script Parameters # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # scriptVersion="1.4.0" export PATH=/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin/ scriptLog="/var/tmp/org.churchofjesuschrist.log" JH="/Library/Application Support/JAMF/bin/jamfHelper.app/Contents/MacOS/jamfHelper" fullScreenTimeout="30" # Number of seconds for full-screen messages to display windowType="${4:-"hud"}" # [ hud | utility | full screen ] icon="${5:-"/System/Library/CoreServices/Finder.app/Contents/Resources/Finder.icns"}" # Absolute path title="${6:-"Title [Parameter 6]"}" # Sets the window's title to the specified string heading="${7:-"Heading [Parameter 7]"}" # Sets the heading of the window to the specified string description="${8:-"Description [Parameter 8] goes here, which can be as long as needed. 'fullScreenTimeout' is currently set to '$fullScreenTimeout' seconds"}" # Sets the main contents of the window to the specified string button1="${9:-"Button1 [P9]"}" # Creates a default button with the specified label button2="${10:-"Button2 [P10]"}" # Creates a second button with the specified label action="${11:-"/System/Applications/Utilities/Digital Color Meter.app"}" # Action (i.e., 'open ...')
- Ensure you’re using a testing Mac and repeat the most recent Terminal command by pressing the up arrow once then pressing Return
- After the longest
17
seconds of your life, confirm that Jamf Helper’sfullscreen
window automatically terminates and Digital Color Meter automatically launches
sudo bash ~/Downloads/Actionable-message-with-Jamf-Helper-reference.bash Caffeinating this script (PID: 26759) 2023-01-18 00:51:55 - ### # Display Message with Jamf Helper and Action (1.4.0) ### 2023-01-18 00:51:55 - The following message will be displayed to the end-user: 2023-01-18 00:51:55 - Title [Parameter 6] Heading [Parameter 7] Description [Parameter 8] goes here, which can be as long as needed. 'fullScreenTimeout' is currently set to '17' seconds Button1 [P9] /System/Applications/Utilities/Digital Color Meter.app 2023-01-18 00:51:57 - Pausing for 17 seconds … kill -term 26779 /Users/dan/Downloads/Actionable-message-with-Jamf-Helper-reference.bash: line 158: 26779 Terminated: 15 /System/Library/CoreServices/RemoteManagement/AppleVNCServer.bundle/Contents/Support/LockScreen.app/Contents/MacOS/LockScreen kill -term 26782 2023-01-18 00:52:15 - Open /System/Applications/Utilities/Digital Color Meter.app ... 2023-01-18 00:52:15 - Result of user's interaction: 2023-01-18 00:52:15 - dan cancelled. 2023-01-18 00:52:15 - De-caffeinate … 2023-01-18 00:52:15 - Attempting to terminate the 'caffeinate' process … 2023-01-18 00:52:15 - (Termination message indicates success.) /Users/dan/Downloads/Actionable-message-with-Jamf-Helper-reference.bash: line 110: 26761 Terminated: 15 caffeinate -dimsu -w $$ 2023-01-18 00:52:15 - Goodbye!
B. Add the Actionable message with Jamf Helper script to your Jamf Pro server
- Add the Actionable message with Jamf Helper script to your Jamf Pro server
- Edit the
scriptLog
path to the desired location for your organization - Change
fullScreenTimeout
to the desired duration
- Edit the
- Specify the following for Options > Parameter Labels
- Parameter 4:
Window Type [ hud | utility | fullscreen ]
- Parameter 5:
Icon (absolute path)
- Parameter 6:
Title
- Parameter 7:
Heading
- Parameter 8:
Description
- Parameter 9:
Default Button Text
- Parameter 10:
Cancel Button Text
- Parameter 11:
Action [ jamfselfservice://content?entity=policy&id=988&action=view ]
- Parameter 4:
- Click Save
Latest version availble on GitHub.
#!/bin/bash #################################################################################################### # # ABOUT # # Actionable messages with Jamf Helper # See: https://snelson.us/2023/01/jamf-helper/ # #################################################################################################### # # HISTORY # # Version 1.0.0, 05-Nov-2014, Dan K. Snelson, Original # Version 1.1.0, 15-Nov-2014, Dan K. Snelson, Added logging # Version 1.2.0, 14-Oct-2016, Dan K. Snelson, Added action to open paramter 10 # Version 1.3.0, 06-May-2022, Dan K. Snelson, Check for and exit if OS is greater than macOS Big Sur 11 # Version 1.4.0, 18-Jan-2023, Dan K. Snelson, Added timeout for full screen mode # #################################################################################################### #################################################################################################### # # Pre-flight Checks # #################################################################################################### # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Confirm script is running as root # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # if [[ $(id -u) -ne 0 ]]; then echo "This script must be run as root; exiting." exit 1 fi # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Ensure computer does not go to sleep while running this script (thanks, @grahampugh!) # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # echo "Caffeinating this script (PID: $$)" caffeinate -dimsu -w $$ & # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Validate logged-in user # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # loggedInUser=$( echo "show State:/Users/ConsoleUser" | scutil | awk '/Name :/ { print $3 }' ) if [[ -z "${loggedInUser}" || "${loggedInUser}" == "loginwindow" ]]; then echo "No user logged-in; exiting." exit #1 else loggedInUserID=$(id -u "${loggedInUser}") fi #################################################################################################### # # Variables # #################################################################################################### # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Script Version and Jamf Pro Script Parameters # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # scriptVersion="1.4.0" export PATH=/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin/ scriptLog="/var/tmp/org.churchofjesuschrist.log" JH="/Library/Application Support/JAMF/bin/jamfHelper.app/Contents/MacOS/jamfHelper" fullScreenTimeout="30" # Number of seconds for the fullscreen messages to display windowType="${4:-"hud"}" # [ hud | utility | fullscreen ] icon="${5:-"/System/Library/CoreServices/Finder.app/Contents/Resources/Finder.icns"}" # Absolute path title="${6:-"Title [Parameter 6]"}" # Sets the window's title to the specified string heading="${7:-"Heading [Parameter 7]"}" # Sets the heading of the window to the specified string description="${8:-"Description [Parameter 8] goes here, which can be as long as needed. 'fullScreenTimeout' is currently set to '$fullScreenTimeout' seconds"}" # Sets the main contents of the window to the specified string button1="${9:-"Button1 [P9]"}" # Creates a default button with the specified label button2="${10:-"Button2 [P10]"}" # Creates a second button with the specified label action="${11:-"/System/Applications/Utilities/Digital Color Meter.app"}" # Action (i.e., 'open ...') #################################################################################################### # # Functions # #################################################################################################### # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Client-side Script Logging # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # function updateScriptLog() { echo -e "$( date +%Y-%m-%d\ %H:%M:%S ) - ${1}" | tee -a "${scriptLog}" } # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Kill a specified process (thanks, @grahampugh!) # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # function killProcess() { process="$1" if process_pid=$( pgrep -a "${process}" 2>/dev/null ) ; then updateScriptLog "Attempting to terminate the '$process' process …" updateScriptLog "(Termination message indicates success.)" kill "$process_pid" 2> /dev/null if pgrep -a "$process" >/dev/null ; then updateScriptLog "ERROR: '$process' could not be terminated." fi else updateScriptLog "The '$process' process isn't running." fi } #################################################################################################### # # Program # #################################################################################################### # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Client-side Logging # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # if [[ ! -f "${scriptLog}" ]]; then touch "${scriptLog}" updateScriptLog "*** Created log file via script ***" fi # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Logging preamble # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # updateScriptLog "\n\n###\n# Display Message with Jamf Helper and Action (${scriptVersion})\n###\n" # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Display Message # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # updateScriptLog "The following message will be displayed to the end-user:" updateScriptLog "${title} ${heading} ${description} ${button1} ${action}" case "${windowType}" in "full screen" | "fullscreen" | "fs" ) osascript -e "set Volume 6" afplay /System/Library/Sounds/Blow.aiff /System/Library/CoreServices/RemoteManagement/AppleVNCServer.bundle/Contents/Support/LockScreen.app/Contents/MacOS/LockScreen & displayMessage=$( "$JH" -windowType "fs" -icon "${icon}" -heading "${heading}" -alignHeading center -description "${description}" ) & updateScriptLog "Pausing for ${fullScreenTimeout} seconds …" sleep "${fullScreenTimeout}" killall -v LockScreen killall -v jamfHelper updateScriptLog "Open ${action} ..." su - "${loggedInUser}" -c "/usr/bin/open '${action}'" ;; * ) displayMessage=$( "$JH" -windowType "${windowType}" -icon "${icon}" -windowPosition ur -title "${title}" -heading "${heading}" -description "${description}" -alignHeading left -button1 "${button1}" -button2 "${button2}" -defaultButton 1 -cancelButton 2 ) ;; esac updateScriptLog "Result of user's interaction: ${displayMessage}" if [[ "${displayMessage}" == "0" ]]; then updateScriptLog "Open ${action} ..." /usr/bin/su \- "${loggedInUser}" -c "/usr/bin/open '${action}'" updateScriptLog "${title} ${heading} ${description} ${button1} ${action}" else updateScriptLog "${loggedInUser} cancelled." fi # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Exit # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # updateScriptLog "De-caffeinate …" killProcess "caffeinate" updateScriptLog "Goodbye!" exit 0
C. Create a Jamf Pro Policy to display an end-user message
- Create a new Jamf Pro Policy, using the following as a guide for Options > General:
- Set Display Name to
Message: Upgrade to macOS Ventura (for Catalina and earlier)
- Set Trigger to
Recurring Check-in
- Set Execution Frequency to the desired value
- Set Display Name to
- Select the Scripts payload and add the Actionable message with Jamf Helper script
- Specify the Parameter Values
- Window Type:
fullscreen
- Icon:
/System/Library/CoreServices/Install Command Line Developer Tools.app/Contents/Resources/SoftwareUpdate.icns
- Title:
Unsupported Operating System
- Heading:
Upgrade to macOS Ventura
- Description:
Your Mac is currently running an unsupported operating system.Please login to the Workforce App Store and learn what to do before upgrading to macOS Ventura.If you need assistance, please contact the Global Services Department+1 (801) 555-1212 and mention KB0054571.
- Default Button Text:
Open
- Cancel Button Text:
Close
- Action:
jamfselfservice://content?entity=policy&id=459&action=view
- Window Type:
- Adjust Scope to your liking
- Click Save
Bonus: Line-breaking Voodoo
Achieving line breaks in Jamf Pro Script Parameters is not always straightforward.
What seems to work well for us is Unicode Character U+2028: