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.pngand 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-installscript 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
swiftDialoginstallation policy, by selecting the Scripts payload and adding thescript, 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 Notificationsscript 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)