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 Progress
script 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
swiftDialog 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 totrue
if 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