Provide your users more detailed feedback when updating inventory via Jamf Pro Self Service
Background
While conducting some internal training earlier this week, one of our TSRs asked: “Is updating inventory where the blue circle just spins and spins but doesn’t appear to do anything?”
“Yes,” was my deflated reply.
Hopefully after implementing this script, you’ll never have to be asked that question again.
Overview

TL;DR
The TL;DR of this approach is to modify your existing Self Service Inventory Update policy using the script below to better provide your users with more detailed feedback.
Configuration
Complete the following steps to provide your user more detailed feedback when they update inventory via Jamf Pro Self Service.
A. Add the swiftDialog Inventory Update Progress script to your Jamf Pro server
- Add the
swiftDialog Inventory Update Progressscript to your Jamf Pro server - Specify the following for Options > Parameter Labels
- Parameter 4:
Script Log Location - Parameter 5:
Estimated Total Seconds - Parameter 6:
Debug Mode [ true | false (default) ]
- Parameter 4:
- Click Save

Latest version available on GitHub.
#!/bin/bash
####################################################################################################
#
# swiftDialog Inventory Update Progress
# https://snelson.us/2022/10/inventory-update-progress/
#
# Purpose: Provide more detailed feedback on Jamf Pro Self Service Inventory Update
#
####################################################################################################
#
# HISTORY
#
# Version 0.0.1, 13-Oct-2022, Dan K. Snelson (@dan-snelson)
# Original version
#
# Version 0.0.2, 14-Oct-2022, Dan K. Snelson (@dan-snelson)
# Added logic to simply update inventory for OSes too old for swiftDialog
#
# Version 0.0.3, 18-Oct-2022, Dan K. Snelson (@dan-snelson)
# Added "debug mode" for auditing Extension Attribute execution time
#
####################################################################################################
####################################################################################################
#
# Variables
#
####################################################################################################
scriptVersion="0.0.3"
export PATH=/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin/
loggedInUser=$( echo "show State:/Users/ConsoleUser" | scutil | awk '/Name :/ { print $3 }' )
osVersion=$( /usr/bin/sw_vers -productVersion )
osMajorVersion=$( echo "${osVersion}" | /usr/bin/awk -F '.' '{print $1}' )
dialogApp="/usr/local/bin/dialog"
dialogLog=$( mktemp /var/tmp/dialogLog.XXX )
inventoryLog=$( mktemp /var/tmp/inventoryLog.XXX )
scriptLog="${4:-"/var/tmp/org.churchofjesuschrist.log"}"
estimatedTotalSeconds="${5:-"298"}"
debugMode="${6:-"false"}"
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# "Inventory Update" Dialog Title, Message and Icon
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
title="Updating Inventory"
message="Please wait while inventory is updated …"
icon=$( defaults read /Library/Preferences/com.jamfsoftware.jamf.plist self_service_app_path )
inventoryProgressText="Initializing …"
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# "Inventory Update" Dialog Settings and Features
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
dialogInventoryUpdate="$dialogApp
--title "$title"
--message "$message"
--icon "$icon"
--mini
--moveable
--progress
--progresstext "$inventoryProgressText"
--quitkey K
--commandfile "$dialogLog" "
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Validate logged-in user
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
if [[ -z "${loggedInUser}" || "${loggedInUser}" == "loginwindow" ]]; then
echo "No user logged-in; exiting."
exit 0
# else
# uid=$(id -u "${loggedInUser}")
fi
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Validate Operating System
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
if [[ "${osMajorVersion}" -ge 11 ]] ; then
echo "macOS ${osMajorVersion} installed; proceeding ..."
else
echo "macOS ${osMajorVersion} installed; updating inventory sans progress …"
/usr/local/bin/jamf recon -endUsername "${loggedInUser}" --verbose >> "$inventoryLog" &
exit 0
fi
####################################################################################################
#
# Functions
#
####################################################################################################
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Client-side Script Logging
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
function updateScriptLog() {
echo -e "$( date +%Y-%m-%d %H:%M:%S ) ${1}" | tee -a "${scriptLog}"
}
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# JAMF Display Message (for fallback in case swiftDialog fails to install)
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
function jamfDisplayMessage() {
updateScriptLog "Jamf Display Message: ${1}"
/usr/local/jamf/bin/jamf displayMessage -message "${1}" &
}
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Check for / install swiftDialog (thanks, Adam!)
# https://github.com/acodega/dialog-scripts/blob/main/dialogCheckFunction.sh
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
function dialogCheck(){
# Get the URL of the latest PKG From the Dialog GitHub repo
dialogURL=$(curl --silent --fail "https://api.github.com/repos/bartreardon/swiftDialog/releases/latest" | awk -F '"' "/browser_download_url/ && /pkg"/ { print $4; exit }")
# Expected Team ID of the downloaded PKG
expectedDialogTeamID="PWA5E9TQ59"
# Check for Dialog and install if not found
if [ ! -e "/Library/Application Support/Dialog/Dialog.app" ]; then
updateScriptLog "Dialog not found. Installing..."
# Create temporary working directory
workDirectory=$( /usr/bin/basename "$0" )
tempDirectory=$( /usr/bin/mktemp -d "/private/tmp/$workDirectory.XXXXXX" )
# Download the installer package
/usr/bin/curl --location --silent "$dialogURL" -o "$tempDirectory/Dialog.pkg"
# Verify the download
teamID=$(/usr/sbin/spctl -a -vv -t install "$tempDirectory/Dialog.pkg" 2>&1 | awk '/origin=/ {print $NF }' | tr -d '()')
# Install the package if Team ID validates
if [ "$expectedDialogTeamID" = "$teamID" ] || [ "$expectedDialogTeamID" = "" ]; then
/usr/sbin/installer -pkg "$tempDirectory/Dialog.pkg" -target /
else
jamfDisplayMessage "Dialog Team ID verification failed."
exit 1
fi
# Remove the temporary working directory when done
/bin/rm -Rf "$tempDirectory"
else
updateScriptLog "swiftDialog version $(dialog --version) found; proceeding..."
fi
}
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Quit Script (thanks, @bartreadon!)
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
function quitScript() {
updateScriptLog "Quitting …"
updateDialog "quit: "
sleep 1
updateScriptLog "Exiting …"
# brutal hack - need to find a better way
killall tail
# Remove dialogLog
if [[ -e ${dialogLog} ]]; then
updateScriptLog "Removing ${dialogLog} …"
rm "${dialogLog}"
fi
# Remove inventoryLog
if [[ -e ${inventoryLog} ]]; then
updateScriptLog "Removing ${inventoryLog} …"
rm "${inventoryLog}"
fi
updateScriptLog "Goodbye!"
exit 0
}
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Update Dialog
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
function updateDialog() {
echo "${1}" >> "${dialogLog}"
sleep 0.4
}
####################################################################################################
#
# Program
#
####################################################################################################
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Confirm script is running as root
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
if [[ $(id -u) -ne 0 ]]; then
echo "This script must be run as root; exiting."
exit 1
fi
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Client-side Logging
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
if [[ ! -f "${scriptLog}" ]]; then
touch "${scriptLog}"
echo "$( date +%Y-%m-%d %H:%M:%S ) *** Created log file via script ***" >>"${scriptLog}"
fi
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Logging preamble
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
if [[ ${debugMode} == "true" ]]; then
updateScriptLog "DEBUG MODE | swiftDialog Inventory Update Progress (${scriptVersion})"
else
updateScriptLog "swiftDialog Inventory Update Progress (${scriptVersion})"
fi
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Validate swiftDialog is installed
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
dialogCheck
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Create "Inventory Update" dialog
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
updateScriptLog "Create Inventory Update dialog …"
eval "$dialogInventoryUpdate" &
if [[ ${debugMode} == "true" ]]; then
sleep 0.5
updateDialog "title: DEBUG MODE | $title"
updateDialog "message: Please wait while a DEBUG inventory is submitted …"
fi
SECONDS="0"
updateDialog "progress: 1"
/usr/local/bin/jamf recon -endUsername "${loggedInUser}" --verbose >> "$inventoryLog" &
until [[ "$inventoryProgressText" == "Submitting data to"* ]]; do
progressPercentage=$( echo "scale=2 ; ( $SECONDS / $estimatedTotalSeconds ) * 100" | bc )
updateDialog "progress: ${progressPercentage}"
# if [[ ${debugMode} == "true" ]]; then
# updateScriptLog "DEBUG MODE | progress: ${progressPercentage}"
# fi
inventoryProgressText=$( tail -n1 "$inventoryLog" | sed -e 's/verbose: //g' -e 's/Found app: /System/Applications///g' -e 's/Utilities///g' -e 's/Found app: /Applications///g' -e 's/Running script for the extension attribute //g' )
updateDialog "progresstext: ${inventoryProgressText}"
if [[ ${debugMode} == "true" ]]; then
updateScriptLog "DEBUG MODE | progresstext: ${inventoryProgressText}"
fi
done
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Complete "Inventory Update" dialog
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
updateScriptLog "Complete Inventory Update dialog"
updateDialog "message: Inventory update complete"
updateDialog "progress: 100"
updateDialog "progresstext: Elasped Time: $(printf '%dh:%dm:%dsn' $((SECONDS/3600)) $((SECONDS%3600/60)) $((SECONDS%60)))"
updateScriptLog "Elasped Time: $(printf '%dh:%dm:%dsn' $((SECONDS/3600)) $((SECONDS%3600/60)) $((SECONDS%60)))"
sleep 3
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Exit
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
quitScript
B. Clone and Modify your Current Self Service Inventory Update Policy
- Clone your current Self Service Inventory Update policy
- Append Options > General > Display Name with
(swiftDialog Progress) - Remove all scripts from Options > Scripts
- Add the
scriptswiftDialog Inventory Update Progress - Specify the Parameter Values
- Script Log Location (i.e., the location of your client-side logs)
- Estimated Total Seconds (i.e., the average number of seconds an update inventory normally takes to complete in your environment)
- Debug Mode (i.e., defaults to
false; set totrueif you’d like to audit Extension Attribute execution durations)
- Remove Maintenance > Update Inventory
- Click Save

Testing
To determine the correct value for Estimated Total Seconds, review the execution times of your current Self Service inventory update script and error on the upper-end of your findings.
Racing Stripes
The screencast shows the Self Service description auto-closing and Self Service auto-refreshing.
If you’d like to implement these features, please see an earlier post Refresh Self Service when users Opt-in / Opt-out of your Internal Beta Test Program.
Updates
14-Oct-2022
# Version 0.0.2, 14-Oct-2022, Dan K. Snelson (@dan-snelson) # Added logic to simply update inventory for OSes too old for swiftDialog
18-Oct-2022
# Version 0.0.3, 18-Oct-2022, Dan K. Snelson (@dan-snelson) # Added "debug mode" for auditing Extension Attribute execution time

Mac Admin Feedback
trevoredwards
Very cool! My users have made similar complaints.
Got this implemented inside 15 minutes and it looks great!
Jamf Nation