Easily create simple macOS Notifications

Background
For the last several weeks, the now 550+ users who frequent the MacAdmin’s Slack #swiftDialog channel have been all abuzz about Bart Reardon’s soon-to-be-released version 2
of swiftDialog
.
One of the features I’ve personally been anxious to try is macOS Notifications via swiftDialog, but as Bart explained when he closed the feature request with wontfix
, Apple’s restrictions conflict with what many Mac Admins require: Branded Notifications.
Voodoo
Then, two days ago, Bart posted:
Special bonus installer – Same build as RC2 but with some voodoo in the pkg
Place an image (recommended 512×512
png
) at/Library/Application Support/Dialog/Dialog.png
and then run the installer.
Two words: It works!
Configuration
After reviewing Bart’s Notifications documentation — including deploying the necessary Configuration Profile — complete the following steps to create simple end-user Notifications via swiftDialog 2
.
Dry-run Test
❯ sudo bash ~/Downloads/swiftDialog\ Notifications.bash 2022-11-16 05:38:25 - ### # swiftDialog Notifications (0.0.1) ### 2022-11-16 05:38:25 - Parameter 5 is NOT populated; displaying instructions … 2022-11-16 05:38:25 - Title: Title [Parameter 5] goes here 2022-11-16 05:38:25 - Subtitle: Subtitle [Parameter 6] goes here 2022-11-16 05:38:25 - Message: Message [Parameter 7] goes here 2022-11-16 05:38:25 - Quitting … 2022-11-16 05:38:25 - Removing /var/tmp/dialogNotificationLog.23K … 2022-11-16 05:38:25 - Goodbye!

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.
- 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/2022/11/macos-notifications-via-swiftdialog-0-0-1/ # #################################################################################################### # # 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) # #################################################################################################### #################################################################################################### # # Variables # #################################################################################################### # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Global Variables # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # scriptVersion="0.0.2" export PATH=/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin/ loggedInUser=$( echo "show State:/Users/ConsoleUser" | scutil | awk '/Name :/ { print $3 }' ) scriptLog="${4:-"/var/tmp/org.churchofjesuschrist.log"}" #################################################################################################### # # Functions # #################################################################################################### # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Client-side Script Logging # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # function updateScriptLog() { echo -e "$( date +%Y-%m-%d\ %H:%M:%S ) - ${1}" | tee -a "${scriptLog}" } #################################################################################################### # # 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 # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Validate logged-in user # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # if [[ -z "${loggedInUser}" || "${loggedInUser}" == "loginwindow" ]]; then echo "No user logged-in; failing back to last logged-in user …" loggedInUser=$( last -1 -t ttys000 | awk '{print $1}' ) fi # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Client-side Logging # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # if [[ ! -f "${scriptLog}" ]]; then touch "${scriptLog}" updateScriptLog "*** Created log file via script ***" fi # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Logging preamble # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # updateScriptLog "\n\n###\n# swiftDialog Pre-install (${scriptVersion})\n###\n" # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # 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 # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Copy Self Service Branding Image # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # updateScriptLog "Copy 'brandingimage.png' …" cp -v "/Users/${loggedInUser}/Library/Application Support/com.jamfsoftware.selfservice.mac/Documents/Images/brandingimage.png" "/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 create sucessfully." ls -lah "/Library/Application Support/Dialog/Dialog.png" 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/chflags hidden "/Library/Application Support/Dialog/" ; /usr/bin/su \- "`/usr/bin/stat -f%Su /dev/console`" -c "/usr/bin/open '/Library/Application Support/Dialog/Dialog.app'" ; /bin/chmod -v 744 /usr/local/bin/dialog ; ls -lah /usr/local/bin/dialog ; /usr/local/bin/jamf recon
- 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/2022/11/macos-notifications-via-swiftdialog-0-0-1/ # #################################################################################################### # # HISTORY # # Version 0.0.1, 14-Nov-2022, Dan K. Snelson (@dan-snelson) # Original proof-of-concept version # #################################################################################################### #################################################################################################### # # Variables # #################################################################################################### # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Global Variables # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # scriptVersion="0.0.1" export PATH=/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin/ 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 #################################################################################################### # # Functions # #################################################################################################### # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Client-side Script Logging # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # function updateScriptLog() { echo -e "$( date +%Y-%m-%d\ %H:%M:%S ) - ${1}" | tee -a "${scriptLog}" } # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Quit Script (thanks, @bartreadon!) # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # function quitScript() { updateScriptLog "Quitting …" # Remove dialogNotificationLog if [[ -e ${dialogNotificationLog} ]]; then updateScriptLog "Removing ${dialogNotificationLog} …" rm "${dialogNotificationLog}" fi updateScriptLog "Goodbye!" exit "${1}" } #################################################################################################### # # 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 # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Validate logged-in user # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # if [[ -z "${loggedInUser}" || "${loggedInUser}" == "loginwindow" ]]; then echo "No user logged-in; exiting." exit 0 # else # uid=$(id -u "${loggedInUser}") fi # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Client-side Logging # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # if [[ ! -f "${scriptLog}" ]]; then touch "${scriptLog}" updateScriptLog "*** Created log file via script ***" fi # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Logging preamble # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # updateScriptLog "\n\n###\n# swiftDialog Notifications (${scriptVersion})\n###\n" # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # 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" exit 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
Display Notification Test (0.0.1)
- 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:
macOS Notifications
- Subtitle:
with swiftDialog 2
- Message:
Coming soon
- 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:
Test Notifications (0.0.1)
- 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 the correct settings for au.bartreardon.dialog
Notifications, the logged-in user had to first launch Dialog at least once before a Notification would display.
# Notifications are not allowed for this application /usr/bin/su \- "`/usr/bin/stat -f%Su /dev/console`" -c "/usr/bin/open '/Library/Application Support/Dialog/Dialog.app'" # Jamf Pro Policy Log The application cannot be opened for an unexpected reason, error=Error Domain=NSOSStatusErrorDomain Code=-600 "procNotFound: no eligible process with specified descriptor" UserInfo={_LSLine=388, _LSFunction=_LSAnnotateAndSendAppleEventWithOptions}
Updates
swiftDialog Pre-install.bash
0.0.2
(16-Nov-2022)
- Added “last logged-in user” logic
- Added check for Dialog.png (with graceful exit)