A pair of scripts to help Jamf Pro admins easily display custom branded macOS Notifications
swiftDialog Pre-install (0.0.3) & swiftDialog Notifications (0.0.3)

Introduction
One of the more welcome features of swiftDialog 2.0 are macOS Notifications. When leveraged with Script Parameters, Jamf Pro administrators can easily display custom branded macOS Notifications to their users.

Configuration
After reviewing Bart’s Notifications documentation — including deploying the necessary Configuration Profile — complete the following steps to create custom branded macOS Notifications via swiftDialog 2
.
A. Add the swiftDialog Pre-install script to your Jamf Pro server
The swiftDialog Pre-install script automates the creation of Dialog.png
, based on your customized Self Service icon (thanks, @meschwartz).
- Add the
swiftDialog Pre-install
script to your Jamf Pro server - Specify the following for Options > Parameter Labels
- Parameter 4:
Script Log Location
- Parameter 4:
- Click Save

Latest version available on GitHub.
#!/bin/bash #################################################################################################### # # ABOUT # # swiftDialog Pre-install # Pre-install Company Logo for swiftDialog v2 Notifications # # See: https://snelson.us/2023/03/swiftdialog-notifications/ # #################################################################################################### # # HISTORY # # Version 0.0.1, 14-Nov-2022, Dan K. Snelson (@dan-snelson) # - Original proof-of-concept version # # Version 0.0.2, 16-Nov-2022, Dan K. Snelson (@dan-snelson) # - Added "last logged-in user" logic # - Added check for Dialog.png (with graceful exit) # # Version 0.0.3, 16-Mar-2023, Dan K. Snelson (@dan-snelson) # - Create 'Dialog.png' from Self Service's custom icon (thanks, @meschwartz!) # - Remove no longer required 'loggedInUser'-related code # #################################################################################################### #################################################################################################### # # Variables # #################################################################################################### # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Global Variables # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # scriptVersion="0.0.3" export PATH=/usr/bin:/bin:/usr/sbin:/sbin scriptLog="${4:-"/var/tmp/org.churchofjesuschrist.log"}" #################################################################################################### # # Pre-flight Checks # #################################################################################################### # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Pre-flight Check: Client-side Logging # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # if [[ ! -f "${scriptLog}" ]]; then touch "${scriptLog}" fi # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Pre-flight Check: Client-side Script Logging Function # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # function updateScriptLog() { echo -e "$( date +%Y-%m-%d\ %H:%M:%S ) - ${1}" | tee -a "${scriptLog}" } # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Pre-flight Check: Logging Preamble # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # updateScriptLog "\n\n###\n# swiftDialog Pre-install (${scriptVersion})\n# https://snelson.us\n###\n" updateScriptLog "PRE-FLIGHT CHECK: Initiating …" # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Pre-flight Check: Confirm script is running as root # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # if [[ $(id -u) -ne 0 ]]; then updateScriptLog "PRE-FLIGHT CHECK: This script must be run as root; exiting." exit 1 fi # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Pre-flight Check: Complete # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # updateScriptLog "PRE-FLIGHT CHECK: Complete" #################################################################################################### # # Program # #################################################################################################### # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Validate Dialog Branding Image # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # updateScriptLog "Validate 'Dialog.png' …" if [[ -f "/Library/Application Support/Dialog/Dialog.png" ]]; then updateScriptLog "The file '/Library/Application Support/Dialog/Dialog.png' already exists; exiting." exit 0 else updateScriptLog "The file '/Library/Application Support/Dialog/Dialog.png' does NOT exist; proceeding …" fi # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Create Dialog directory # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # if [[ ! -d "/Library/Application Support/Dialog/" ]]; then updateScriptLog "Creating '/Library/Application Support/Dialog/' …" mkdir -p "/Library/Application Support/Dialog/" else updateScriptLog "The directory '/Library/Application Support/Dialog/' exists …" fi # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Create Dialog.png from Self Service's custom icon (thanks, @meschwartz!) # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # updateScriptLog "Create 'Dialog.png' …" xxd -p -s 260 "$(defaults read /Library/Preferences/com.jamfsoftware.jamf self_service_app_path)"/Icon$'\r'/..namedfork/rsrc | xxd -r -p > "/Library/Application Support/Dialog/Dialog.png" # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Validate Dialog Branding Image # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # updateScriptLog "Validate 'Dialog.png' …" if [[ ! -f "/Library/Application Support/Dialog/Dialog.png" ]]; then updateScriptLog "Error: The file '/Library/Application Support/Dialog/Dialog.png' was NOT found." exit 1 else updateScriptLog "The file '/Library/Application Support/Dialog/Dialog.png' was created sucessfully." find "/Library/Application Support/Dialog/Dialog.png" | tee -a "${scriptLog}" fi # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Exit # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # updateScriptLog "End-of-line." exit 0
B. Modify your swiftDialog installation policy
- Modify your
swiftDialog
installation policy, by selecting the Scripts payload and adding the
script, specifying the following Parameter ValueswiftDialog Pre-install
- Script Log Location:
/var/log/com.company.log
- Script Log Location:
- Add the Files and Processes payload and specify the following experimental one-liner for the Execute Command
/usr/bin/su - "$(/usr/bin/stat -f%Su /dev/console)" -c "/usr/bin/open '/Library/Application Support/Dialog/Dialog.app'" ; /usr/local/bin/dialog --notification --title "Greetings from IT" --message "You may safely dismiss this test Notification"
- Click Save

C. Add the swiftDialog Notifications script to your Jamf Pro server
- Add the
swiftDialog Notifications
script to your Jamf Pro server - Specify the following for Options > Parameter Labels
- Parameter 4:
Script Log Location
- Parameter 5:
Title
- Parameter 6:
Subtitle
- Parameter 7:
Message
- Parameter 4:
- Click Save

Latest version available on GitHub.
#!/bin/bash #################################################################################################### # # ABOUT # # swiftDialog Notifications # # See: https://snelson.us/2023/03/swiftdialog-notifications/ # #################################################################################################### # # HISTORY # # Version 0.0.1, 14-Nov-2022, Dan K. Snelson (@dan-snelson) # - Original proof-of-concept version # # Version 0.0.3, 16-Mar-2023, Dan K. Snelson (@dan-snelson) # - Updates from 'swiftDialog Pre-install.bash' # - Matched version number of 'swiftDialog Pre-install.bash' # #################################################################################################### #################################################################################################### # # Variables # #################################################################################################### # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Global Variables # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # scriptVersion="0.0.3" export PATH=/usr/bin:/bin:/usr/sbin:/sbin loggedInUser=$( echo "show State:/Users/ConsoleUser" | scutil | awk '/Name :/ { print $3 }' ) dialogApp="/usr/local/bin/dialog" dialogNotificationLog=$( mktemp /var/tmp/dialogNotificationLog.XXX ) scriptLog="${4:-"/var/tmp/org.churchofjesuschrist.log"}" if [[ -n ${5} ]]; then titleoption="--title"; title="${5}"; fi if [[ -n ${6} ]]; then subtitleoption="--subtitle"; subtitle="${6}"; fi if [[ -n ${7} ]]; then messageoption="--message"; message="${7}"; fi #################################################################################################### # # Pre-flight Checks # #################################################################################################### # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Pre-flight Check: Client-side Logging # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # if [[ ! -f "${scriptLog}" ]]; then touch "${scriptLog}" fi # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Pre-flight Check: Client-side Script Logging Function # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # function updateScriptLog() { echo -e "$( date +%Y-%m-%d\ %H:%M:%S ) - ${1}" | tee -a "${scriptLog}" } # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Pre-flight Check: Current Logged-in User Function # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # function currentLoggedInUser() { loggedInUser=$( echo "show State:/Users/ConsoleUser" | scutil | awk '/Name :/ { print $3 }' ) updateScriptLog "PRE-FLIGHT CHECK: Current Logged-in User: ${loggedInUser}" } # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Pre-flight Check: Logging Preamble # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # updateScriptLog "\n\n###\n# swiftDialog Notifications (${scriptVersion})\n# https://snelson.us\n###\n" updateScriptLog "PRE-FLIGHT CHECK: Initiating …" # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Pre-flight Check: Confirm script is running as root # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # if [[ $(id -u) -ne 0 ]]; then updateScriptLog "PRE-FLIGHT CHECK: This script must be run as root; exiting." exit 1 fi # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Pre-flight Check: Validate logged-in user # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # currentLoggedInUser if [[ -z "${loggedInUser}" || "${loggedInUser}" == "loginwindow" ]]; then updateScriptLog "PRE-FLIGHT CHECK: No user logged-in; exiting" exit 1 fi # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Pre-flight Check: Complete # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # updateScriptLog "PRE-FLIGHT CHECK: Complete" #################################################################################################### # # Functions # #################################################################################################### # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Quit Script (thanks, @bartreadon!) # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # function quitScript() { updateScriptLog "Quitting …" # Remove dialogNotificationLog if [[ -e ${dialogNotificationLog} ]]; then updateScriptLog "Removing ${dialogNotificationLog} …" rm "${dialogNotificationLog}" fi updateScriptLog "Goodbye!" exit "${1}" } # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Validate Script Parameters # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # if [[ -z "${title}" ]] ; then updateScriptLog "Parameter 5 is NOT populated; displaying instructions …" titleoption="--title" title="Title [Parameter 5] goes here" subtitleoption="--subtitle" subtitle="Subtitle [Parameter 6] goes here" messageoption="--message" message="Message [Parameter 7] goes here" else updateScriptLog "Parameters 5, \"title,\" is populated; proceeding ..." fi # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Display Notification # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # updateScriptLog "Title: ${title}" updateScriptLog "Subtitle: ${subtitle}" updateScriptLog "Message: ${message}" ${dialogApp} \ --notification \ "${titleoption}" "${title}" \ "${subtitleoption}" "${subtitle}" \ "${messageoption}" "${message}" \ --commandfile "$dialogNotificationLog}" # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Exit # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # quitScript "0"
D. Create a test Jamf Pro policy to display the notification
- Create a new Jamf Pro policy, using the following as a guide for Options > General:
- Set Display Name to
swfitDialog Notification Test (0.0.3)
- Set Execution Frequency to
Ongoing
- Set Display Name to
- Select the Scripts payload and add the
script, specifying the following Parameter ValuesswiftDialog Notifications
- Script Log Location:
/var/log/com.company.log
- Title:
Custom Branded macOS Notifications
- Subtitle (blank)
- Message:
with swiftDialog 2
- Script Log Location:

- Adjust Scope to your liking; we limited testing policies to our opt-in Beta Testers
- Use the following for Self Service
- Self Service Display Name:
swfitDialog Notification Test (0.0.3)
- Button Name Before Initiation:
Execute
- Button Name After Initiation:
Execute
- Description:
Tests macOS Notifications with swiftDialog
- Self Service Display Name:
- Click Save
Testing Notes
Through trial-and-error, we discovered that even with our preferred settings for au.bartreardon.dialog
Notifications …

au.bartreardon.dialog
)… the logged-in user had to first launch Dialog at least once before a Notification would display.
Now, we include the following Files and Processes payload, Execute Command, as one of our last steps in Setup Your Mac (after which the computer is restarted):
/usr/bin/su - "$(/usr/bin/stat -f%Su /dev/console)" -c "/usr/bin/open '/Library/Application Support/Dialog/Dialog.app'" ; /usr/local/bin/dialog --notification --title "Setup Your Mac" --message "Finalizing configuration …"
