Skip to main content
Question

Having problems with Dock configuration


Forum|alt.badge.img+3

I have created a configuration profile for the dock. I tried to do it with Dock Master and the dock resets after the computer reboots. (sounds like working as intended, however I do not want to have it this restrictive) Then I tried iMazing Profile Editor and the dock reset as well and the magnification got locked. 

so really want I want to do is to Crate a dock, place the icons, and then the user can modify it as they wish in the exception to removing 2 icons that must stay.

4 replies

mm2270
Forum|alt.badge.img+16
  • Legendary Contributor
  • 7880 replies
  • October 18, 2023

"so really want I want to do is to Crate a dock, place the icons, and then the user can modify it as they wish in the exception to removing 2 icons that must stay."

Unfortunately what you're asking for here is really not easy at all. Almost impossible unless you have an ongoing policy that keeps adding those 2 dock items in if it finds them missing. Generally speaking the options for setting up the Dock fall into one of these types.

1. Configuration Profile, which usually makes the Dock immutable, cannot be altered by the user. Sounds like you don't want that.

2. Use a script and LaunchAgent that calls dockutil to set up the Dock how you want it, but only do it once, and then let the user make modifications as they would like. But that would mean they can also remove the 2 icons you want to always have.

3. Push just the 2 icons you want to their Dock using the Jamf Pro built in Dock icons function, which, I'm going to be honest, I haven't used in a few years now, so I honestly don't know if it still works or not?

As I mentioned, there is no option I'm aware of where you can make 90% of the Dock modifiable, and 10% of it immutable. Apple simply doesn't allow us to get that granular when it comes to the Dock (and a great many other things too)

If you really want that, you will have to use something like dockutil and have an ongoing policy that runs a script to call dockutil and keeps checking to see if the icons you need are in the user's Dock, and if they aren't, add them back in. You can't prevent the users from removing the icons, but you can add them back in each time the policy runs. That's about the best I can think of.


Forum|alt.badge.img+3

how would I do it with a script?


Forum|alt.badge.img+3
TheCookieMonsta wrote:

how would I do it with a script?


I tried this one, but its not working for me:

 

#!/bin/bash

## This allows you to specify lists of items to remove and add in arrays, and then they'll be done in bulk using a for loop
## Items to remove should be the label (usually the name of the application)
## Items to add are the full path to the item to add (usually /Applications/NAMEOFAPP.app)
## A few examples are prepopulated in the arrays, but feel free to tweak as suits the needs of your organization

# original https://raw.githubusercontent.com/aysiu/Mac-Scripts-and-Profiles/master/DockutilAddRemoveArrays.sh
# bash string manipulations here https://www.tldp.org/LDP/LG/issue18/bash.html

# TO-DO:
# - check for jamf
# - check for dockutil; install from jamf (or download from site)
# - check for AD binding, add Directory Utility if bound
# - check OS version, add System Prefs vs System Settings
# - check OS version, add Safari from proper location

# check for dockutil, call policy if not present

if [[ ! -e "/usr/local/bin/dockutil" ]]; then
/usr/local/bin/jamf policy -event install-dockutil
fi

itemsToRemove=(
"Address Book"
"App Store"
"Books"
"Calendar"
"Contacts"
"Dictionary"
"Downloads"
"FaceTime"
"Freehand"
"iBooks"
"iPhoto"
"iTunes"
"Keynote"
"Launchpad"
"Mail"
"Maps"
"Messages"
"Mission Control"
"Music"
"News"
"Notes"
"Numbers"
"Pages"
"Photos"
"Podcasts"
"Reminders"
"Siri"
"Stocks"
"TextEdit"
"TV"
)

itemsToAdd=(
"//Applications/Bayview App Store.app"
"//Applications/Microsoft Teams (work or school).app"
"//Applications/Microsoft Outlook.app"
"//Applications/Microsoft Word.app"
"//Applications/Microsoft Excel.app"
"//Applications/Microsoft To Do.app"
"//Applications/Microsoft Remote Desktop.app"
"//System/Applications/System Settings.app"
)

for removalItem in "${itemsToRemove[@]}"
do
# Check that the item is actually in the Dock
inDock=$(/usr/local/bin/dockutil --list | /usr/bin/grep "$removalItem")
if [ -n "$inDock" ]; then
/usr/local/bin/dockutil --remove "$removalItem" --no-restart
fi
done


for additionItem in "${itemsToAdd[@]}"
do
# Check that the item actually exists to be added to the Dock and that it isn't already in the Dock
# Stripping path and extension code based on code from http://stackoverflow.com/a/2664746
additionItemString=${additionItem##*/}
additionItemBasename=${additionItemString%.*}
inDock=$(/usr/local/bin/dockutil --list | /usr/bin/grep "$additionItemBasename")
if [ -e "$additionItem" ] && [ -z "$inDock" ]; then
/usr/local/bin/dockutil --add "$additionItem" --no-restart
fi
done

sleep 3

/usr/bin/killall Dock


mm2270
Forum|alt.badge.img+16
  • Legendary Contributor
  • 7880 replies
  • October 19, 2023
TheCookieMonsta wrote:

I tried this one, but its not working for me:

 

#!/bin/bash

## This allows you to specify lists of items to remove and add in arrays, and then they'll be done in bulk using a for loop
## Items to remove should be the label (usually the name of the application)
## Items to add are the full path to the item to add (usually /Applications/NAMEOFAPP.app)
## A few examples are prepopulated in the arrays, but feel free to tweak as suits the needs of your organization

# original https://raw.githubusercontent.com/aysiu/Mac-Scripts-and-Profiles/master/DockutilAddRemoveArrays.sh
# bash string manipulations here https://www.tldp.org/LDP/LG/issue18/bash.html

# TO-DO:
# - check for jamf
# - check for dockutil; install from jamf (or download from site)
# - check for AD binding, add Directory Utility if bound
# - check OS version, add System Prefs vs System Settings
# - check OS version, add Safari from proper location

# check for dockutil, call policy if not present

if [[ ! -e "/usr/local/bin/dockutil" ]]; then
/usr/local/bin/jamf policy -event install-dockutil
fi

itemsToRemove=(
"Address Book"
"App Store"
"Books"
"Calendar"
"Contacts"
"Dictionary"
"Downloads"
"FaceTime"
"Freehand"
"iBooks"
"iPhoto"
"iTunes"
"Keynote"
"Launchpad"
"Mail"
"Maps"
"Messages"
"Mission Control"
"Music"
"News"
"Notes"
"Numbers"
"Pages"
"Photos"
"Podcasts"
"Reminders"
"Siri"
"Stocks"
"TextEdit"
"TV"
)

itemsToAdd=(
"//Applications/Bayview App Store.app"
"//Applications/Microsoft Teams (work or school).app"
"//Applications/Microsoft Outlook.app"
"//Applications/Microsoft Word.app"
"//Applications/Microsoft Excel.app"
"//Applications/Microsoft To Do.app"
"//Applications/Microsoft Remote Desktop.app"
"//System/Applications/System Settings.app"
)

for removalItem in "${itemsToRemove[@]}"
do
# Check that the item is actually in the Dock
inDock=$(/usr/local/bin/dockutil --list | /usr/bin/grep "$removalItem")
if [ -n "$inDock" ]; then
/usr/local/bin/dockutil --remove "$removalItem" --no-restart
fi
done


for additionItem in "${itemsToAdd[@]}"
do
# Check that the item actually exists to be added to the Dock and that it isn't already in the Dock
# Stripping path and extension code based on code from http://stackoverflow.com/a/2664746
additionItemString=${additionItem##*/}
additionItemBasename=${additionItemString%.*}
inDock=$(/usr/local/bin/dockutil --list | /usr/bin/grep "$additionItemBasename")
if [ -e "$additionItem" ] && [ -z "$inDock" ]; then
/usr/local/bin/dockutil --add "$additionItem" --no-restart
fi
done

sleep 3

/usr/bin/killall Dock


So, while dockutil is a great and useful tool, one of the points people get tripped up on with it is that for it to really work, it has to be called as the user logged into the device. Either that, or you have to tell dockutil which dock.plist to work on. Because Jamf always runs scripts as root, it tends to cause issues when invoking dockutil unless you do one of those 2 options.

My preference has always been the former - to run the script calling dockutil as the logged in user. Basically, I create a script out to disk on the fly from within a script run by Jamf, then create a LaunchAgent on the fly that calls that script and load the LaunchAgent as the user. Since LaunchAgents run as the logged in user, it's always calling dockutil as the person on the machine, not as root.

Here's an example of the script I'm using (modified to remove my org specific details) that can be used to set up a Dock with icons after first login. This will not continue to add in any missing dock icons. That's something you'll need to work on incorporating by using some of dockutil's functionality to check the dock for items. I would suggest a similar approach of using a LaunchAgent that calls a script periodically to check for those items, and add them if they are missing.

#!/bin/bash org="Organization-name-or-acronym" ## Edit this to suit your environment !! ## Get the logged in username logged_in_user=$(/usr/sbin/scutil <<< "show State:/Users/ConsoleUser" | /usr/bin/awk '/Name :/ && ! /loginwindow/ {print $3}') ## Get the logged in username UID logged_in_uid=$(id -u "$logged_in_user") ## Path to the dockutil binary dockutil_path="/usr/local/bin/dockutil" ## Path to the LaunchAgent plist launchagent_name="/Library/LaunchAgents/com.$org.dockconfig.plist" ## Path to the local script script_name="/private/var/configureDock-$org.sh" #################################### START OF SCRIPT CREATION #################################### ## Create the local script cat << EOSCRIPT > "$script_name" #!/bin/bash retry_count="0" logged_in_user=\\$(/usr/sbin/scutil <<< "show State:/Users/ConsoleUser" | awk '/Name :/ && ! /loginwindow/ {print \\$3}') ## path to Dockutil binary dockutil_path="/usr/local/bin/dockutil" setup_done_plist="/Users/\\${logged_in_user}/Library/Preferences/com.\\$org.dockconfig.plist" ## Check that the Dock is running before doing anything until [[ \\$(ps axc | grep "Dock" 2>&1 > /dev/null; echo \\$?) == 0 ]]; do sleep 1 done ## Function to set up the Dock with the desired items function setUpDock () { ## Array to store the items to be added to the Dock dock_items+=( "/System/Applications/System Preferences.app" "/Applications/Safari.app" "/Applications/Google Chrome.app" "/Applications/Microsoft Outlook.app" "/Applications/Microsoft Word.app" "/Applications/Microsoft Excel.app" "/Applications/Microsoft PowerPoint.app" "/Applications/Microsoft Teams.app" "/Applications/Self Service.app" ) ## Now add items to the Dock qty="\\${#dock_items[@]}" echo "Number of items to add to the Dock: \\$qty" ## This loops over the items in the above dock_items array, adding in each item to the Dock in order. ## It will keep track of the number of items being added, and when reaching the last one, restarts the Dock i=1; while read dock_item; do ## First check to make sure the application is on disk at the specified path if [ -d "\\$dock_item" ]; then ## Now check to see if we have reached the end of the array of items or not if [[ "\\$i" -lt "\\$qty" ]]; then ## If not at the end, add the item in with the --no-restart flag "\\$dockutil_path" --add "\\$dock_item" --no-restart ## Added brief pause between each --add operation to allow ## the Dock.plist time to catch up with the changes /bin/sleep 0.7 else ## Or add it in without the flag to have the Dock restart "\\$dockutil_path" --add "\\$dock_item" fi else ## If the app couldn't be found, make a note of it and skip it echo "The path to \\$dock_item could not be found. Skipping..." fi let i=\\$((i+1)) done < <(printf '%s\\n' "\\${dock_items[@]}") ## After completion of the above steps, we check to make sure all the items we expected added have been added, ## or we make a second attempt at adding the missing items ## Get list of the current Dock items current_dock_items=$("\\$dockutil_path" --list | /usr/bin/awk -F'file:' '{print \\$1}' | /usr/bin/sed 's/ //g') ## Place items into an array for comparison while read item; do current_dock_arr+=("\\$item") done < <(printf '%s\\n' "\\$current_dock_items") ## Get difference between the 2 arrays diff=\\$(/bin/echo \\${dock_items[@]} \\${current_dock_arr[@]} | /usr/bin/tr ' ' '\\n' | /usr/bin/sort | /usr/bin/uniq -u) if [ "\\$diff" != "" ]; then if [ "\\$retry_count" -lt 1 ]; then retry_count=\\$((retry_count+1)) setUpDock else /bin/echo "Already made one retry attempt. Finalizing and exiting as is..." ## Turn off the show recents option for the Dock /usr/bin/defaults write com.apple.dock show-recents -bool false ## Set a flag in a user level plist to indicate the configuration is complete /usr/bin/defaults write "\\$setup_done_plist" DockSetupComplete -bool true exit 0 fi else /bin/echo "All items accounted for in the current Dock. Finalizing and exiting..." /usr/bin/defaults write com.apple.dock show-recents -bool false ## Set a flag in a user level plist to indicate the configuration is complete /usr/bin/defaults write "\\$setup_done_plist" DockSetupComplete -bool true exit 0 fi } function clearDock () { ## First, remove all items from the standard Dock "\\$dockutil_path" --remove all ## Wait 1 second sleep 2 ## Now run the setupDock function to add apps setUpDock } ## Check that this user account has not had the Dock already configured dock_setup_check=\\$(/usr/bin/defaults read "\\$setup_done_plist" DockSetupComplete 2>/dev/null) if [[ -z "\\$dock_setup_check" ]]; then clearDock elif [[ "\\$dock_setup_check" == "1" ]]; then echo "Dock setup completed for this account. Exiting..." exit 0 fi exit 0 EOSCRIPT ##################################### END OF SCRIPT CREATION ##################################### ## Fix permissions on the script /bin/chmod +x "$script_name" /usr/sbin/chown root:admin "$script_name" ## Create the LaunchAgent plist using defaults /usr/bin/defaults write "$launchagent_name" Label "com.$org.dockconfig" /usr/bin/defaults write "$launchagent_name" Program "/private/var/configureDock-$org.sh" /usr/bin/defaults write "$launchagent_name" RunAtLoad -bool true ## Fix permissions and ownership on the LaunchAgent plist /bin/chmod 644 "$launchagent_name" /usr/sbin/chown root:wheel "$launchagent_name"

 

One thing not added to this script is launching the LaunchAgent. I don't do this here, as I prefer to wait until after the machine has rebooted. When the user logs in, the agent activates, does it's thing, makes a note that it ran once and then doesn't run again (the script). You could add something to kick off the LaunchAgent to this after it creates it though.


Reply


Cookie policy

We use cookies to enhance and personalize your experience. If you accept you agree to our full cookie policy. Learn more about our cookies.

 
Cookie settings