Menu Close

macOS Notifications (0.0.1) via swiftDialog

Easily create simple macOS Notifications

Branded swiftDialog Notifications compared to Jamf Pro built-in 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.

  1. Add the swiftDialog Pre-install script to your Jamf Pro server
  2. Specify the following for Options > Parameter Labels
    • Parameter 4: Script Log Location
  3. 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
  1. Modify your swiftDialog installation policy, by selecting the Scripts payload and adding the swiftDialog Pre-install script, specifying the following Parameter Value
    • Script Log Location: /var/log/com.company.log
  2. 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
  1. Click Save
C. Add the swiftDialog Notifications script to your Jamf Pro server
  1. Add the swiftDialog Notifications script to your Jamf Pro server
  2. Specify the following for Options > Parameter Labels
    • Parameter 4: Script Log Location
    • Parameter 5: Title
    • Parameter 6: Subtitle
    • Parameter 7: Message
  3. 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
  1. 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
  2. Select the Scripts payload and add the swiftDialog Notifications script, specifying the following Parameter Values
    • Script Log Location: /var/log/com.company.log
    • Title: macOS Notifications
    • Subtitle: with swiftDialog 2
    • Message: Coming soon
  1. Adjust Scope to your liking; we limited testing policies to our opt-in Beta Testers
  2. 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
  1. 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)
Posted in macOS, Tips & Tricks

Related Posts