Menu Close

Actionable messages with Jamf Helper

For older macOS versions when swiftDialog isn’t an option, leverage Jamf Helper to provide your users actionable messages

fullscreen jamfHelper message
“fullscreen” jamfHelper message auto-terminates after fullScreenTimeout
“utility” jamfHelper message
“hud” jamfHelper message

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 in fullscreen 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:

/Library/Application Support/JAMF/bin/jamfHelper.app

Jamf Pro Documentation, Overview of Technologies, Applications and Utilities

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.

  1. Open the macOS Terminal.
  2. 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
  1. 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
Window Type [Parameter 4]: hud
  1. 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]
  2. Click Button1 [P9] (i.e., Default) and observe that Digital Color Meter launches, then review the output in Terminal
The default action (Parameter 11 ) launches Digital Color Meter
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!
  1. Quit Digital Color Meter and repeat the most recent Terminal command by pressing the up arrow once then pressing Return
  2. 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!
  1. 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 from 30 to 17
    • Line 79: Change the value of the windowType variable from hud to fullscreen

Note: If you observe a warning about unusual line terminators, click Ignore

Click Ignore if prompted to remove unusual line terminators
####################################################################################################
#
# 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 ...')
  1. Ensure you’re using a testing Mac and repeat the most recent Terminal command by pressing the up arrow once then pressing Return
Window Type [Parameter 4]: fullscreen
  1. After the longest 17 seconds of your life, confirm that Jamf Helper’s fullscreen window automatically terminates and Digital Color Meter automatically launches
The default action (Parameter 11 ) always executes when using fullscreen
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
  1. 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
  2. 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 ]
  3. 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
  1. 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
  2. Select the Scripts payload and add the Actionable message with Jamf Helper script
  3. 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
  4. Adjust Scope to your liking
  5. 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:

Unicode Character U+2028 at Line 83, Columns 88 and 89
Unicode Character U+2028
“fullscreen” jamfHelper message with line breaks courtesy of Unicode Character U+2028
Posted in Jamf Pro, Scripts, Tips & Tricks

Related Posts