├── .gitignore
├── DockBuilder-component.plist
├── README.md
├── build.sh
├── com.github.ryangball.dockbuilder.defaults.plist
├── com.github.ryangball.dockbuilder.plist
├── dockbuilder.sh
├── dockutil.pkg
├── images
└── dock_message.png
└── postinstall.sh
/.gitignore:
--------------------------------------------------------------------------------
1 | build/*
2 | dockbuilder.sh.old
3 | .DS_Store
--------------------------------------------------------------------------------
/DockBuilder-component.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | BundleIsRelocatable
7 |
8 | BundleIsVersionChecked
9 |
10 | BundleOverwriteAction
11 | upgrade
12 | RootRelativeBundlePath
13 | Applications/Utilities/DockBuilder.app
14 |
15 |
16 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # DockBuilder
2 | A LaunchAgent and .app to build a user's Dock upon login and/or on demand.
3 |
4 | DockBuilder allows for the building of a user's Dock based on an organization's needs. DockBuilder eliminates the need for a user template which only allows for a static Dock for all users, and template manipulation can cause issues in newer versions of macOS. DockBuilder not only allows for easy creation of a new user's Dock out of the box, but also has the potential to dynamically set up a different Dock for users based on some criteria; like AD groups for example (you'd have to modify the source based on your criteria).
5 |
6 | ## Features
7 | - Builds a Dock based on pre-defined defaults
8 | - Includes a framework for building unique Docks for certain users based on some criteria (including an example)
9 | - Logs to ~/Library/Logs/DockBuilder.log (by default)
10 | - Does not start until the Dock.app is loaded upon login
11 | - Only builds a Dock for user's who's Dock is younger than 300 seconds (to minimize re-building a pre-existing user's Dock after the installation of DockBuilder)
12 | - Option to hide the Dock and display a message to the user while the Dock is being built
13 |
14 |
15 |
16 |
17 |
18 | ## Requirements for Building
19 | - [Platypus](https://sveinbjorn.org/platypus): A developer tool that creates native Mac applications from command line scripts such as shell scripts or Python, Perl, Ruby, Tcl, JavaScript and PHP programs.
20 | - You must install the command line tool associated with Platypus. Open Platypus, in the Menu Bar choose "Platypus" > "Preferences" and click the "Install" button to install the Platypus command line tool.
21 | - jamfHelper: jamfHelper is used to display the message when the Dock is being built (if you choose to use that feature). CocoaDialog could also be leveraged pretty easily for environments without Jamf Pro. AppleScript could also be used, but you can't create an AppleScript dialog void of buttons.
22 |
23 | *Note: [Dockutil](https://github.com/ryangball/DockBuilder#Dockutil) is also required, but included in the resulting .pkg and releases.*
24 |
25 | ## Build Project
26 | To build new versions you can simply run the [build.sh](/build.sh) script and specify a version number for both the .app and .pkg. The resulting .pkg will include the LaunchAgent and .app as well as necessary preinstall/postinstall scripts. If you do not include a version number as a parameter then version 1.0 will be assigned as the default.
27 | ```bash
28 | # Clone the repo and traverse into the created directory
29 | git clone https://github.com/ryangball/DockBuilder.git
30 | cd DockBuilder
31 |
32 | # At this point you'd customize the variables in the build.sh script
33 |
34 | # Build the .pkg
35 | ./build.sh 1.5
36 | ```
37 |
38 | ## Customize DockBuilder
39 | Within the [build.sh](/build.sh) script, you can modify the top-most variables to create a custom DockBuilder .app and .pkg.
40 |
41 | Some things to keep in mind:
42 | 1. Within both the breadcrumb and log variables, you'll notice the $HOME environmental variable. You should leave this in there as both should be in the user's home folder.
43 | 2. Within the defaultItemsToAdd array (and alternateItemsToAdd_1 if you use it), you need to follow the same pattern that I used in the example. When specifying view options for the persistent-others Dock items, you need to separate the Dock item and options with a comma (",") as per the example.
44 | 3. After modifying the variables in build.sh, please test for full functionality before deploying.
45 | 4. If you want to set up a unique Dock for certain users you must populate the alternateItemsToAdd_1 ion [build.sh](/build.sh) **and** modify [this logic in dockbuilder.sh](https://github.com/ryangball/DockBuilder/blob/e6c4bab519648bdcdc812293bdd0ad098a798cc9/dockbuilder.sh#L108-L119)) to include the users or criteria to build the alternate Dock.
46 | 5. If you want to exclude specific existing users from the initial breadcrumb creation so that they will get a new Dock created, you must populate the skipInitialBreadcrumbUsers variable in [build.sh](/build.sh).
47 |
48 | ## Testing
49 | To test DockBuilder, install the .pkg, then unload/load/start the LaunchAgent.
50 | ```bash
51 | # Delete the breadcrumb for the user if it exists
52 | find ~/Library/Preferences -name com.github.ryangball.dockbuilder.breadcrumb.plist -delete
53 |
54 | # Unload the LaunchAgent
55 | launchctl unload /Library/LaunchAgents/com.github.ryangball.dockbuilder.plist
56 |
57 | # Load the LaunchAgent
58 | launchctl load /Library/LaunchAgents/com.github.ryangball.dockbuilder.plist
59 |
60 | # Start the LaunchAgent (if necessary)
61 | launchctl start com.github.ryangball.dockbuilder
62 |
63 | # Tail the log to see what is occurring
64 | tail -f ~/Library/Logs/DockBuilder.log
65 | ```
66 |
67 | ## Re-create a User's Dock
68 | Upon DockBuilder's execution, a breadcrumb is placed into the user's home folder by default: ~/Library/Preferences/com.github.ryangball.dockbuilder.breadcrumb.plist
69 |
70 | In the event that this breadcrumb exists for a user, DockBuilder will exit without any action. To re-create a user's Dock, open terminal as the user and run the following to remove the breadcrumb:
71 | ```bash
72 | rm ~/Library/Preferences/com.github.ryangball.dockbuilder.breadcrumb.plist
73 | ```
74 | Then you can simply run the /Applications/Utilities/DockBuilder.app or unload/load the LaunchAgent as per the [Testing](https://github.com/ryangball/DockBuilder#Testing) section above.
75 |
76 | ## Dockutil
77 | [Dockutil](https://github.com/kcrawford/dockutil) is included in the resulting .pkg and is licensed under the [Apache 2.0](http://www.apache.org/licenses/LICENSE-2.0) license. Dockutil is automatically downloaded from the releases section when using the build.sh script, or included if you download one of the DockBuilder Releases.
--------------------------------------------------------------------------------
/build.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | #shellcheck disable=SC2088,SC2016
3 |
4 | # Identifier for the .app and .pkg
5 | identifier="com.github.ryangball.dockbuilder"
6 |
7 | # Version of the .app and .pkg, you can leave this alone and specify at the command line
8 | version="1.0"
9 |
10 | # Path and filename of the main property list used to store preferences for the .app
11 | preferenceFileFullPath="/Library/Preferences/com.github.ryangball.dockbuilder.defaults.plist"
12 |
13 | # Path to the breadcrumb dropped when DockBuilder runs for a user, this should be in the user's home folder
14 | # Note: You should keep this in single quotes and don't remove the $HOME environmental variable
15 | breadcrumb='$HOME/Library/Preferences/com.github.ryangball.dockbuilder.breadcrumb.plist'
16 |
17 | # Path to the DockBuilder log, this should be in the user's home folder
18 | # Note: You should keep this in single quotes and don't remove the $HOME environmental variable
19 | log='$HOME/Library/Logs/DockBuilder.log'
20 |
21 | # The icon for the .app
22 | appIcon="/System/Library/CoreServices/Dock.app/Contents/Resources/Dock.icns"
23 |
24 | # Determines if the user's Dock is hidden while being built for the first time
25 | hideDockWhileBuilding="true" # (true|false)
26 |
27 | # If the above variable is set to true, the message below will be displayed
28 | hideDockMessage="Your Mac's Dock is being built for the first time."
29 |
30 | # Array of users where a breadcrumb will not be created during the postinstall
31 | # Handy if you want to force a new Dock for a user that might have existed already
32 | skipInitialBreadcrumbUsers=("admin" "admin2")
33 |
34 | # Array to hold all the items we need to add for a default Dock
35 | # Note: if you need to add options you must seperate the item from the options with a , (comma)
36 | # Example: "/Applications/,--view grid --display stack --sort name"
37 | # This will add the /Applications folder to the persistent-others section of the Dock and sets
38 | # the view to grid, the display to stack, and sorts by name.
39 | # All options available here: https://github.com/kcrawford/dockutil
40 | defaultItemsToAdd=(
41 | "/Applications/System Preferences.app/"
42 | "/Applications/Self Service.app/"
43 | "/Applications/Safari.app/"
44 | "/Applications/Google Chrome.app/"
45 | "/Applications/App Store.app/"
46 | "/Applications/Utilities/Console.app/"
47 | "/Applications/Utilities/Terminal.app/"
48 | "/Applications/,--view grid --display stack --sort name"
49 | "~/Downloads"
50 | )
51 |
52 | # Array to hold all the items we need to add for an alternate Dock
53 | # Be sure to change the logic under the "Set up the Dock" comment in dockbuilder.sh if you want
54 | # to use this alternate Dock for a specific user/users
55 | alternateItemsToAdd_1=(
56 | "/Applications/System Preferences.app/"
57 | "/Applications/Safari.app/"
58 | "/Applications/App Store.app/"
59 | "/System/Library/CoreServices/Applications/Directory Utility.app/"
60 | "/Applications/Utilities/Activity Monitor.app/"
61 | "/Applications/Utilities/Console.app/"
62 | "/Applications/Utilities/Terminal.app/"
63 | "/System/Library/CoreServices/Applications/Network Utility.app/"
64 | "/Applications/Utilities/Disk Utility.app/"
65 | "/Applications/Utilities/Keychain Access.app/"
66 | "/Applications/,--view grid --display stack --sort name"
67 | "~/Downloads"
68 | )
69 |
70 | ########### It is not necessary to edit beyond this point, do at your own risk ###########
71 |
72 | function install_dockutil_pkg () {
73 | if [[ -e /private/tmp/DockBuilder/files/usr/local/bin/dockutil ]]; then
74 | echo "dockutil binary has been installed in test build directory"
75 | else
76 | pkgutil --expand-full "$PWD/dockutil.pkg" /private/tmp/DockBuilder/temp
77 | cp -R /private/tmp/DockBuilder/temp/Payload/usr /private/tmp/DockBuilder/files/
78 | rm -R /private/tmp/DockBuilder/temp
79 | fi
80 |
81 | if [[ ! -e /private/tmp/DockBuilder/files/usr/local/bin/dockutil ]]; then
82 | echo "dockutil binary failed to install in the temp build directory; exiting."
83 | exit 1
84 | fi
85 | }
86 |
87 | function get_dockutil_pkg () {
88 | latestDockutilReleaseURL=$(curl -s https://api.github.com/repos/kcrawford/dockutil/releases/latest | python -c 'import json,sys;obj=json.load(sys.stdin);print obj["assets"][0]["browser_download_url"];')
89 | if [[ ! -e "$PWD/dockutil.pkg" ]]; then
90 | echo "Getting the latest version of dockutil..."
91 | curl -L "$latestDockutilReleaseURL" > "$PWD/dockutil.pkg"
92 | install_dockutil_pkg
93 | fi
94 | }
95 |
96 | # Check for platypus command line, bail if it does not exist
97 | if [[ ! -f /usr/local/bin/platypus ]]; then
98 | echo "Platypus command line tool not installed, see the following URL for more information:"
99 | echo "https://github.com/ryangball/DockBuilder/blob/master/README.md#requirements-for-building"
100 | fi
101 |
102 | # Update the variables in the dockbuilder.sh script
103 | # If you know of a more elegant/efficient way to do this please create a PR
104 | sed -i '' "s#preferenceFileFullPath=.*#preferenceFileFullPath=\"$preferenceFileFullPath\"#" "$PWD/dockbuilder.sh"
105 | sed -i '' "s#preferenceFileFullPath=.*#preferenceFileFullPath=\"$preferenceFileFullPath\"#" "$PWD/postinstall.sh"
106 |
107 | # Create clean temp build directories
108 | find /private/tmp/DockBuilder -mindepth 1 -delete
109 | mkdir -p /private/tmp/DockBuilder/files/Applications/Utilities
110 | mkdir -p /private/tmp/DockBuilder/files/Library/LaunchAgents
111 | mkdir -p /private/tmp/DockBuilder/files/Library/Preferences
112 | mkdir -p /private/tmp/DockBuilder/scripts
113 | mkdir -p "$PWD/build"
114 |
115 | # Check for version number as arg 1
116 | if [[ -n "$1" ]]; then
117 | version="$1"
118 | echo "Version set to $version"
119 | else
120 | echo "No version passed, using version $version"
121 | fi
122 |
123 | # Make sure dockutil is in the temp build directory
124 | get_dockutil_pkg
125 | install_dockutil_pkg
126 |
127 | # Clear the default_items plist if it exists
128 | preferenceFileName="${preferenceFileFullPath##*/}"
129 | if [[ -e "$PWD/$preferenceFileName" ]]; then
130 | /usr/libexec/PlistBuddy -c Clear "$PWD/$preferenceFileName"
131 | fi
132 | /usr/libexec/PlistBuddy -c "Add :DefaultItemsToAdd array" "$PWD/$preferenceFileName"
133 | /usr/libexec/PlistBuddy -c "Add :AlternateItemsToAdd_1 array" "$PWD/$preferenceFileName"
134 | /usr/libexec/PlistBuddy -c "Add :SkipInitialBreadcrumbUsers array" "$PWD/$preferenceFileName"
135 |
136 | # Populate our variables into the plist
137 | /usr/bin/plutil -insert BreadcrumbPath -string "$breadcrumb" "$PWD/$preferenceFileName"
138 | /usr/bin/plutil -insert LogPath -string "$log" "$PWD/$preferenceFileName"
139 | /usr/bin/plutil -insert AppIcon -string "$appIcon" "$PWD/$preferenceFileName"
140 | /usr/bin/plutil -insert HideDockWhileBuilding -bool "$hideDockWhileBuilding" "$PWD/$preferenceFileName"
141 | /usr/bin/plutil -insert HideDockMessage -string "$hideDockMessage" "$PWD/$preferenceFileName"
142 |
143 | # Populate our DefaultItemsToAdd array
144 | index="0"
145 | for item in "${defaultItemsToAdd[@]}"; do
146 | plutil -insert DefaultItemsToAdd.$index -string "$item" "$PWD/$preferenceFileName"
147 | ((index++))
148 | done
149 |
150 | # Populate our AlternateItemsToAdd_1 array
151 | index="0"
152 | for item in "${alternateItemsToAdd_1[@]}"; do
153 | plutil -insert AlternateItemsToAdd_1.$index -string "$item" "$PWD/$preferenceFileName"
154 | ((index++))
155 | done
156 |
157 | # Populate our SkipInitialBreadcrumbUsers array
158 | for user in "${skipInitialBreadcrumbUsers[@]}"; do
159 | plutil -insert SkipInitialBreadcrumbUsers.0 -string "$user" "$PWD/$preferenceFileName"
160 | ((index++))
161 | done
162 |
163 | # Ensure the plist is xml
164 | plutil -convert xml1 "$PWD/$preferenceFileName"
165 |
166 | # Build the .app
167 | echo "Building the .app with Platypus..."
168 | /usr/local/bin/platypus \
169 | --background \
170 | --quit-after-execution \
171 | --app-icon "$appIcon" \
172 | --name 'DockBuilder' \
173 | --interface-type 'None' \
174 | --interpreter '/bin/bash' \
175 | --author 'Ryan Ball' \
176 | --app-version "$version" \
177 | --bundle-identifier "$identifier" \
178 | --optimize-nib \
179 | --overwrite \
180 | 'dockbuilder.sh' \
181 | "/private/tmp/DockBuilder/files/Applications/Utilities/DockBuilder.app"
182 |
183 | # Migrate postinstall script to temp build directory
184 | cp "$PWD/postinstall.sh" /private/tmp/DockBuilder/scripts/postinstall
185 | chmod +x /private/tmp/DockBuilder/scripts/postinstall
186 |
187 | # Copy the LaunchAgent plist to the temp build directory
188 | cp "$PWD/com.github.ryangball.dockbuilder.plist" "/private/tmp/DockBuilder/files/Library/LaunchAgents/"
189 |
190 | # Copy the main preference list to the temp build directory
191 | cp "$PWD/$preferenceFileName" "/private/tmp/DockBuilder/files/Library/Preferences/"
192 | chmod 644 "/private/tmp/DockBuilder/files/Library/Preferences/$preferenceFileName"
193 |
194 | # Remove any unwanted .DS_Store files from the temp build directory
195 | find "/private/tmp/DockBuilder/" -name '*.DS_Store' -type f -delete
196 |
197 | # Remove any extended attributes (ACEs) from the temp build directory
198 | /usr/bin/xattr -rc "/private/tmp/DockBuilder"
199 |
200 | echo "Building the PKG..."
201 | /usr/bin/pkgbuild --quiet --root "/private/tmp/DockBuilder/files/" \
202 | --install-location "/" \
203 | --scripts "/private/tmp/DockBuilder/scripts/" \
204 | --identifier "$identifier" \
205 | --version "$version" \
206 | --ownership recommended \
207 | --component-plist "$PWD/DockBuilder-component.plist" \
208 | "$PWD/build/DockBuilder_${version}.pkg"
209 |
210 | exit 0
--------------------------------------------------------------------------------
/com.github.ryangball.dockbuilder.defaults.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | AlternateItemsToAdd_1
6 |
7 | /Applications/System Preferences.app/
8 | /Applications/Safari.app/
9 | /Applications/App Store.app/
10 | /System/Library/CoreServices/Applications/Directory Utility.app/
11 | /Applications/Utilities/Activity Monitor.app/
12 | /Applications/Utilities/Console.app/
13 | /Applications/Utilities/Terminal.app/
14 | /System/Library/CoreServices/Applications/Network Utility.app/
15 | /Applications/Utilities/Disk Utility.app/
16 | /Applications/Utilities/Keychain Access.app/
17 | /Applications/,--view grid --display stack --sort name
18 | ~/Downloads
19 |
20 | AppIcon
21 | /System/Library/CoreServices/Dock.app/Contents/Resources/Dock.icns
22 | BreadcrumbPath
23 | $HOME/Library/Preferences/com.github.ryangball.dockbuilder.breadcrumb.plist
24 | DefaultItemsToAdd
25 |
26 | /Applications/System Preferences.app/
27 | /Applications/Self Service.app/
28 | /Applications/Safari.app/
29 | /Applications/Google Chrome.app/
30 | /Applications/App Store.app/
31 | /Applications/Utilities/Console.app/
32 | /Applications/Utilities/Terminal.app/
33 | /Applications/,--view grid --display stack --sort name
34 | ~/Downloads
35 |
36 | HideDockMessage
37 | Your Mac's Dock is being built for the first time.
38 | HideDockWhileBuilding
39 |
40 | LogPath
41 | $HOME/Library/Logs/DockBuilder.log
42 | SkipInitialBreadcrumbUsers
43 |
44 | admin2
45 | admin
46 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/com.github.ryangball.dockbuilder.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Label
6 | com.github.ryangball.dockbuilder
7 | LimitLoadToSessionType
8 | Aqua
9 | ProgramArguments
10 |
11 | /usr/bin/open
12 | /Applications/Utilities/DockBuilder.app
13 |
14 | RunAtLoad
15 |
16 |
17 |
--------------------------------------------------------------------------------
/dockbuilder.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # These variables will be replaced with values from the build.sh script automagically
4 | preferenceFileFullPath="/Library/Preferences/com.github.ryangball.dockbuilder.defaults.plist"
5 |
6 | ########### It is not necessary to edit beyond this point, do at your own risk ###########
7 | # These variables are populated from the main preference file, created
8 | # with the build.sh script and deployed to clients using resulting .pkg
9 | breadcrumb=$(eval echo "$(/usr/libexec/PlistBuddy -c "Print :BreadcrumbPath" "$preferenceFileFullPath")") # Using eval here to expand $HOME
10 | log=$(eval echo "$(/usr/libexec/PlistBuddy -c "Print :LogPath" "$preferenceFileFullPath")") # Using eval here to expand $HOME
11 | appIcon=$(/usr/libexec/PlistBuddy -c "Print :AppIcon" "$preferenceFileFullPath")
12 | hideDockWhileBuilding=$(/usr/libexec/PlistBuddy -c "Print :HideDockWhileBuilding" "$preferenceFileFullPath")
13 | hideDockMessage=$(/usr/libexec/PlistBuddy -c "Print :HideDockMessage" "$preferenceFileFullPath")
14 | defaultItemsToAddFromPlist=$(/usr/libexec/PlistBuddy -c "Print DefaultItemsToAdd:" "$preferenceFileFullPath" | grep '/' | sed 's/^ *//')
15 | alternateItemsToAdd_1FromPlist=$(/usr/libexec/PlistBuddy -c "Print AlternateItemsToAdd_1:" "$preferenceFileFullPath" | grep '/' | sed 's/^ *//')
16 | loggedInUser=$(/usr/sbin/scutil <<< "show State:/Users/ConsoleUser" | /usr/bin/awk '/Name :/ && ! /loginwindow/ { print $3 }')
17 | scriptName=$(basename "$0")
18 |
19 | function writelog () {
20 | DATE=$(date +%Y-%m-%d\ %H:%M:%S)
21 | /bin/echo "${1}"
22 | /bin/echo "$DATE" " $1" >> "$log"
23 | }
24 |
25 | function finish () {
26 | kill "$jamfHelperPID" 2>/dev/null; wait "$jamfHelperPID" 2>/dev/null
27 | writelog "======== Finished $scriptName ========"
28 | }
29 |
30 | function build_dock () {
31 | for item in "${itemsToAdd[@]}"; do
32 | if [[ "$item" =~ , ]]; then
33 | params=${item##*,}
34 | item=${item%,*}
35 | #shellcheck disable=SC2086
36 | /usr/local/bin/dockutil --add "$item" $params --no-restart "$HOME/Library/Preferences/com.apple.dock.plist" 2>&1 | while read -r LINE; do writelog "$LINE"; done;
37 | else
38 | /usr/local/bin/dockutil --add "$item" --no-restart "$HOME/Library/Preferences/com.apple.dock.plist" 2>&1 | while read -r LINE; do writelog "$LINE"; done;
39 | fi
40 | done
41 | }
42 |
43 | function create_breadcrumb () {
44 | # Create a breadcrumb to track the creation of the Dock
45 | writelog "Creating DockBuilder user breadcrumb."
46 | /usr/bin/defaults write "$breadcrumb" build-date "$(date +%m-%d-%Y)"
47 | /usr/bin/defaults write "$breadcrumb" build-time "$(date +%r)"
48 | }
49 |
50 | trap finish EXIT
51 |
52 | writelog " "
53 | writelog "======== Starting $scriptName ========"
54 |
55 | # Validate we got values from the plist
56 | if [[ -f "$preferenceFileFullPath" ]]; then
57 | # Create array for default items
58 | while read -r line; do
59 | defaultItemsToAdd+=("$line")
60 | done <<< "$defaultItemsToAddFromPlist"
61 |
62 | # Create array for alternate_1 items
63 | while read -r line; do
64 | alternateItemsToAdd_1+=("$line")
65 | done <<< "$alternateItemsToAdd_1FromPlist"
66 |
67 | # Verify that we obtained values for each variable
68 | if [[ -z "$breadcrumb" ]] || [[ -z "$log" ]] || [[ -z "$appIcon" ]] || [[ -z "$hideDockWhileBuilding" ]] || [[ -z "$hideDockMessage" ]] || [[ -z "${defaultItemsToAdd[*]}" ]]; then
69 | writelog "One or more default settings not present in main preference file; exiting."
70 | exit 1
71 | fi
72 | else
73 | writelog "Preference file does not exist; exiting."
74 | exit 1
75 | fi
76 |
77 | # Make sure DockUtil is installed
78 | if [[ ! -f "/usr/local/bin/dockutil" ]]; then
79 | writelog "DockUtil does not exist, exiting."
80 | exit 1
81 | fi
82 |
83 | # We need to wait for the Dock to actually start
84 | until [[ $(pgrep -x Dock) ]]; do
85 | wait
86 | done
87 |
88 | # Check to see if the Dock was previously set up for the user
89 | if [[ -f "$breadcrumb" ]]; then
90 | writelog "DockBuilder ran previously on $(defaults read "$breadcrumb" build-date) at $(defaults read "$breadcrumb" build-time)."
91 | exit 0
92 | fi
93 |
94 | if [[ "$hideDockWhileBuilding" == "true" ]]; then
95 | # Display a jamfHelper dialog box to user informing them that we are configuring their Dock (in background)
96 | writelog "Unloading the Dock."
97 | /Library/Application\ Support/JAMF/bin/jamfHelper.app/Contents/MacOS/jamfHelper -windowType utility -title "DockBuilder" -icon "$appIcon" -description "$hideDockMessage" &
98 | jamfHelperPID=$!
99 |
100 | # Unload the Dock while it is being updated
101 | launchctl unload /System/Library/LaunchAgents/com.apple.Dock.plist
102 | fi
103 |
104 | writelog "Clearing Dock."
105 | /usr/local/bin/dockutil --remove all --no-restart "$HOME/Library/Preferences/com.apple.dock.plist" 2>&1 | while read -r LINE; do writelog "$LINE"; done;
106 | /bin/sleep 5
107 |
108 | # Set up the Dock
109 | if [[ "$loggedInUser" == "admin" ]]; then
110 | writelog "Building alternate_1 Dock."
111 | for item in "${alternateItemsToAdd_1[@]}"; do
112 | itemsToAdd+=("$item")
113 | done
114 | /usr/bin/defaults write "$HOME/Library/Preferences/com.apple.dock.plist" 'orientation' -string 'left' # Position the Dock to the left
115 | else
116 | writelog "Building default Dock."
117 | for item in "${defaultItemsToAdd[@]}"; do
118 | itemsToAdd+=("$item")
119 | done
120 | fi
121 | build_dock
122 | create_breadcrumb
123 |
124 | # Load the Dock if unloaded or restart the Dock
125 | if [[ "$hideDockWhileBuilding" == "true" ]]; then
126 | writelog "Loading the newly built Dock."
127 | launchctl load /System/Library/LaunchAgents/com.apple.Dock.plist
128 | launchctl start com.apple.Dock.agent
129 | else
130 | writelog "Resetting Dock."
131 | /usr/bin/killall Dock
132 | fi
133 |
134 | exit 0
135 |
--------------------------------------------------------------------------------
/dockutil.pkg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ryangball/DockBuilder/d8a955ddfa8c89f276a5f7864b493e5f7096c237/dockutil.pkg
--------------------------------------------------------------------------------
/images/dock_message.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ryangball/DockBuilder/d8a955ddfa8c89f276a5f7864b493e5f7096c237/images/dock_message.png
--------------------------------------------------------------------------------
/postinstall.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | #shellcheck disable=SC2012
3 |
4 | preferenceFileFullPath="/Library/Preferences/com.github.ryangball.dockbuilder.defaults.plist"
5 | breadcrumbPathMinusHome=$(/usr/libexec/PlistBuddy -c "Print BreadcrumbPath" $preferenceFileFullPath | cut -d/ -f2-)
6 | skipInitialBreadcrumbUsers=$(/usr/libexec/PlistBuddy -c "Print SkipInitialBreadcrumbUsers" $preferenceFileFullPath | sed -e 1d -e '$d' | sed 's/^ *//')
7 |
8 | log="/Library/Logs/DockBuilder_Install.log"
9 |
10 | function writelog () {
11 | DATE=$(date +%Y-%m-%d\ %H:%M:%S)
12 | /bin/echo "${1}"
13 | /bin/echo "$DATE" " $1" >> "$log"
14 | }
15 |
16 | create_breadcrumb () {
17 | # Create a breadcrumb to track the creation of the Dock
18 | writelog "Creating DockBuilder user breadcrumb for $1."
19 | /usr/bin/defaults write "$2" build-date "$(date +%m-%d-%Y)"
20 | /usr/bin/defaults write "$2" build-time "$(date +%r)"
21 | chown "$1" "$2"
22 | }
23 |
24 | writelog "Looping through all users to ensure Dock will be configured correctly..."
25 |
26 | # Run through all normal accounts
27 | for userName in $(dscl . -list /Users uid | awk '$2 >= 100 && $0 !~ /^_/ { print $1 }'); do
28 | if [[ "$skipInitialBreadcrumbUsers" =~ $userName ]]; then
29 | writelog "Initial breadcrumb creation for $userName is being skipped."
30 | continue
31 | fi
32 | userHome=$(/usr/bin/dscl . read "/Users/$userName" NFSHomeDirectory | cut -c 19-)
33 | breadcrumb="$userHome/$breadcrumbPathMinusHome"
34 |
35 | # Check to see if a breadcrumb is already created in the user's home folder
36 | if [[ -f "$breadcrumb" ]]; then
37 | writelog "$userName's Dock was built by DockBuilder on $(defaults read "$breadcrumb" build-date) at $(defaults read "$breadcrumb" build-time)."
38 | continue
39 | fi
40 |
41 | # Check to see if the user's home folder exists, and if so get the age in seconds
42 | if [[ -d "$userHome" ]]; then
43 | userHomeAge=$(( $(date +%s)-$(stat -f%B "$userHome") ))
44 | # Check to see if the user's home folder is at least 5 minutes old
45 | if [[ "$userHomeAge" -gt "300" ]]; then
46 | writelog "$userName's home folder has existed since $(stat -f "%SB" -t "%m-%d-%Y" "$userHome") at $(stat -f "%SB" -t "%r" "$userHome")."
47 | # Check to see if the user's home folder contains the dock plist indicating the dock has been built
48 | if [[ -f "$userHome/Library/Preferences/com.apple.dock.plist" ]]; then
49 | create_breadcrumb "$userName" "$breadcrumb"
50 | else
51 | writelog "$userName's Dock has not been created yet, skipping."
52 | fi
53 | else
54 | writelog "$userName's home folder is less than 5 minutes old; skipping."
55 | fi
56 | else
57 | writelog "$userName's Dock has not been created yet, skipping."
58 | fi
59 | done
60 |
61 | # if someone is logged in
62 | if who | grep -q console; then
63 |
64 | # get the logged in user's uid
65 | LOGGED_IN_UID=$(ls -ln /dev/console | awk '{ print $3 }')
66 |
67 | # use launchctl asuser to run launchctl in the same Mach bootstrap namespace hierachy as the Finder
68 | launchctl asuser "$LOGGED_IN_UID" launchctl load /Library/LaunchAgents/com.github.ryangball.dockbuilder.plist
69 | fi
70 |
71 | touch /Applications/Utilities/DockBuilder.app
72 |
73 | exit 0
74 |
--------------------------------------------------------------------------------