You can make a difference in the Apple Support Community!

When you sign up with your Apple Account, you can provide valuable feedback to other community members by upvoting helpful replies and User Tips.

Looks like no one’s replied in a while. To start the conversation again, simply ask a new question.

Removing an application from being persistent in the dock programatically

The solution in this old thread:

Remove from dock - Apple Community

From twtwtw, marked "solved," looks like exactly what I need. But when I actually run that code, it just corrupts the dock preferences and the change back to defaults. Any help on what's going wrong? I presume an OS update since 2012 makes that code fail.

Posted on Apr 3, 2022 3:56 PM

Reply
Question marked as Top-ranking reply

Posted on Apr 14, 2022 8:02 PM

I got it. Had to work on other things for a bit, but with some better Googling, it actually didn't take too long to get working.


etresoft

  • I did consider having permanent apps, with the same name as the real apps, that can live in the Dock where the only thing that "App" actually does is to check what branch they're on and run the correct version. That seemed good at first, but it seemed to me that it gets complicated really fast. Not all users want the same apps in their docks, so the "Real" copies of the apps still need to be executables, not just code run by the "Dock" version. But then when they run the Dock Version, another identical icon for the "Real" version is also going to show up in their Dock... and they'll quit the "Dock" version and not understand why the app is still open... or users will add the "Real" version to their Dock once it's running and have both... I think it's just going to cause confusion.
  • As Camelot pointed out, Kandji can do this, so can your own suggestion of dockutil... and several installers from different developers do it. It's not that crazy. It's editing a text file and restarting the Dock. Yes, Apple could theoretically break it at any time, but that applies to most of what I do for a living. In this case, the section of the Dock Preferences file I'm editing appears to have been consistent for at least 17 years, so I'll take my chances.
  • "I strongly suggest you review what your high-level goals are. What are you trying to accomplish?" <- that's exactly how I got here.


Camelot - thank you for the suggestion! That looks like a more supported, official path, but purchasing an MDM system for the company to solve this one issue is way to big of a "solution." We've evaluated MDM a few times before, and may eventually do it. Good to know this is something it can potentially do.


And the solution:


use framework "Foundation"

use scripting additions


set prefsFile to (POSIX path of (path to preferences from user domain)) & "com.apple.dock.plist"

set removeApps to {"TextEdit"}

set dockRec to my readPlistAt:prefsFile

set appRecords to |persistent-apps| of dockRec

set newAppRecord to {}

repeat with anAppRecord in appRecords

if |file-label| of |tile-data| of anAppRecord is not in removeApps then copy contents of anAppRecord to end of newAppRecord

end repeat

set |persistent-apps| of dockRec to newAppRecord

my saveRecord:dockRec toPlistAt:prefsFile

repeat 2 times

do shell script "killall Dock"

delay 3

end repeat


on saveRecord:theRecord toPlistAt:posixPath

set theDict to current application's NSDictionary's dictionaryWithDictionary:theRecord

set thePath to current application's NSString's stringWithString:posixPath

set thePath to thePath's stringByExpandingTildeInPath()

theDict's writeToFile:thePath atomically:true

end saveRecord:toPlistAt:


on readPlistAt:posixPath

set thePath to current application's NSString's stringWithString:posixPath

set thePath to thePath's stringByExpandingTildeInPath()

set theDict to current application's NSDictionary's dictionaryWithContentsOfFile:thePath

return theDict as record

end readPlistAt:

9 replies
Question marked as Top-ranking reply

Apr 14, 2022 8:02 PM in response to t_spoon

I got it. Had to work on other things for a bit, but with some better Googling, it actually didn't take too long to get working.


etresoft

  • I did consider having permanent apps, with the same name as the real apps, that can live in the Dock where the only thing that "App" actually does is to check what branch they're on and run the correct version. That seemed good at first, but it seemed to me that it gets complicated really fast. Not all users want the same apps in their docks, so the "Real" copies of the apps still need to be executables, not just code run by the "Dock" version. But then when they run the Dock Version, another identical icon for the "Real" version is also going to show up in their Dock... and they'll quit the "Dock" version and not understand why the app is still open... or users will add the "Real" version to their Dock once it's running and have both... I think it's just going to cause confusion.
  • As Camelot pointed out, Kandji can do this, so can your own suggestion of dockutil... and several installers from different developers do it. It's not that crazy. It's editing a text file and restarting the Dock. Yes, Apple could theoretically break it at any time, but that applies to most of what I do for a living. In this case, the section of the Dock Preferences file I'm editing appears to have been consistent for at least 17 years, so I'll take my chances.
  • "I strongly suggest you review what your high-level goals are. What are you trying to accomplish?" <- that's exactly how I got here.


Camelot - thank you for the suggestion! That looks like a more supported, official path, but purchasing an MDM system for the company to solve this one issue is way to big of a "solution." We've evaluated MDM a few times before, and may eventually do it. Good to know this is something it can potentially do.


And the solution:


use framework "Foundation"

use scripting additions


set prefsFile to (POSIX path of (path to preferences from user domain)) & "com.apple.dock.plist"

set removeApps to {"TextEdit"}

set dockRec to my readPlistAt:prefsFile

set appRecords to |persistent-apps| of dockRec

set newAppRecord to {}

repeat with anAppRecord in appRecords

if |file-label| of |tile-data| of anAppRecord is not in removeApps then copy contents of anAppRecord to end of newAppRecord

end repeat

set |persistent-apps| of dockRec to newAppRecord

my saveRecord:dockRec toPlistAt:prefsFile

repeat 2 times

do shell script "killall Dock"

delay 3

end repeat


on saveRecord:theRecord toPlistAt:posixPath

set theDict to current application's NSDictionary's dictionaryWithDictionary:theRecord

set thePath to current application's NSString's stringWithString:posixPath

set thePath to thePath's stringByExpandingTildeInPath()

theDict's writeToFile:thePath atomically:true

end saveRecord:toPlistAt:


on readPlistAt:posixPath

set thePath to current application's NSString's stringWithString:posixPath

set thePath to thePath's stringByExpandingTildeInPath()

set theDict to current application's NSDictionary's dictionaryWithContentsOfFile:thePath

return theDict as record

end readPlistAt:

Apr 4, 2022 9:57 AM in response to t_spoon

t_spoon wrote:

I'm aware of dockutil, which is great, but would involve installing it on a hundred users systems, I'd like to avoid that kind of dependency.

It might also be a way to give you the commands necessary to easily accomplish this task, or failing that, demonstrate that it can't be done reliably.

I had already seen the linked StackOverflow page, but that's about adding items to the Dock, which I can already do. Putting the correct version of the app in the dock is no problem, it's getting the old one out that's a problem.

Indeed. That's why I said that above. There are a couple of different ways to solve this. You can extract the entire array of elements, locate just the one you want to remove, remove it, and then replace the array. You can also find the numeric index of the element you are searching for and attempt to remove just that one. But that might also ultimately require replacing the entire array.

I develop for prepress art. Most of our code base is Applescript... all the apps that I'm deploying here that I need to add/remove from the dock are Applescript. So I don't think I need to avoid it here.

The procedure for removing an element from an array is rather complicated and AppleScript is rather fragile. Plus, I don't even know if AppleScript has a native interface to the defaults system. That previous example you were using was hacking up a plist persistence file from preferences, which wasn't reliable then and definitely isn't today. So you might have to code the AppleScript to do all of this array manipulation via "do shell script". That'll keep you busy. Just don't forget to "killall cfprefsd".

The different versions of the apps are code signed and have unique bundle ID's. This situation happens all the time - for example, many users install multiple versions of Adobe Apps

You had me, or rather, lost me, at "Adobe apps". I've had a number of "discussions" with people regarding various problems with Adobe apps. I've had Senior Adobe Scientists tell me that things I demonstrated in a few minutes are, in fact, impossible. I re-packaged that into an App Store utility to do the impossible.


But I digress. Unique, version-specific bundle IDs are unusual. I'm not disputing you if you say Adobe does that. I'm just glad I don't use Adobe products if that's true. But if your apps are using version-specific bundle IDs, then that would avoid many of the problems I was referring to.

If you look at the dock plist I'm trying to modify here, it keeps track of the app the dock button connects to by its path. Not bundle ID or application name, or anything else that can get confused between versions.

The whole problem with hacking around on some other app's internal data is that those are implementation details. Just because Apple persists the value as a path that you can see doesn't mean that Apple will continue to do that in the future. It doesn't even mean that the Dock uses those paths internally. Apple really prefers to use bundle IDs for launching apps.

We do use git to store different versions of the code. GIT is not a deployment mechanism. You don't put your end users on git and deploy applications to git repositories, git is for managing code.

You can use git for whatever you want.

OK, so most major developers, like Adobe, Microsoft, and of course Apple are doing it wrong, because many of their apps add themselves as persistent to the dock when installed.

No. You simply cited two specific developers who are notorious for ignoring standard conventions (as well as published Apple APIs) and doing it their own way.


You can't count Apple. The Dock is Apple's software. Therefore, Apple can do anything it wants with the Dock. The fact that Apple hasn't published any kind of API for the Dock means that Apple does not support any kind of external manipulation. Apple even makes a point to forbid this behaviour in its Mac App Store Review Guidelines.

But maybe removing old versions isn't standard. Unless they're uninstalled, but I assume that's MacOS, not the installer, automatically removing things that are no longer present.

There is no automatic uninstallation mechanism. There is no uninstallation mechanism of any kind.

I'll keep looking.

I strongly suggest you review what your high-level goals are. What are you trying to accomplish? It is not unusual for people to become fixated on some dead-end path like this and refuse to consider the many, many great alternatives that exist. It is difficult to me list them because they are practically infinite.


If this whole problem is because of old references in the Dock, then use MDM to forbid users from adding their own references. Or maybe pre-populate the Dock with dynamic references that automatically resolve to the previously specified version environment. But if you are determined to only consider one of the few paths that Apple explicitly doesn't support and actively discourages, then your experience is going to be sub-optimal.

Apr 3, 2022 5:43 PM in response to etresoft

Thanks etresoft, but that's not at all what I'm asking.


Some applications live in the dock whether they're running or not. You can make an application stay or not stay by right-clicking it in the dock and selecting "Options - > Keep in dock," checking or unchecking that option. That's the setting for whether or not an application "persists" in the dock.


I need a way for a program to automatically make a program that was set to be persistent not be persistent. The answer would be an Applescript or shell script, like the answers on the page I linked, but one that still works on current OS versions.

Apr 3, 2022 6:32 PM in response to t_spoon

What you are describing is a user setting. Supposedly it is still possible to add apps to the dock, but it is frowned on. I haven't seen any app do that in years.


That AppleScript you referenced was never correct. Those kinds of things maybe worked once 15 years ago and then get endlessly copied and pasted across the internet. Unfortunately, the (apparently) correct code makes use of an "array add" operation. It is easy to add an element to the end of an existing array. But removing a specific element is much more difficult.


It is certainly possible, but why? This happens so rarely these days that it seems like an awful lot of effort for little benefit.

Apr 3, 2022 7:13 PM in response to etresoft

Because we have different development branches for our applications, so there are often several different versions of the same application available on a machine. When a user changes branches of our application suite, the internal references between versions of the applications are all internally consistent. But if a user has added applications to their dock, then those are hard links to certain versions, and they wind up clicking them in the dock and running a version of an application from a different branch of code than all the rest of the applications they're running, which can cause disastrous results. When a user runs our application that allows them to select which code branch they'd like to run off of, I want to check their dock to see which of the applications from our suite they have put in their dock, remove them, and then add the same application back from the branch they're moving to. Adding them back is easy enough, it's removing them that's the problem.


I get a lot of answers on forums that are along the lines of "you shouldn't want to do that." Thanks, but it's really not what I'm looking for. Do you have a better solution, when there are multiple versions of the same application installed on a system, to programmatically insure that any version in the dock refers to the correct original version of the application?


We could create dummy versions of all our apps that live in the Applications folder, and check which branch the user's supposed to be on, and then actually run the appropriate version of the app from the appropriate location, for them to put in their docks. But that would require training all the users not to add them to the dock in normal ways, like dragging them from below the dividing line up to above it. Because that wouldn't get the "dummy app" that's just a shortcut.


Removing items programmatically is definitely they way to go here for our use case. Relative to the costs if users running mutually incompatible applications, the benefits of getting this working are extremely high compared to the costs of figuring it out.

Apr 4, 2022 5:00 AM in response to t_spoon

This is a user-to-user support forum. The normal answer for something like this is “you shouldn’t want to do that”. In your case, however, this does sound like a legitimate developer request, so I’ll answer it as such.


Last night, I did find a StackOverflow post that described the correct way to externally modify the Dock’s preferences. But in searching for that page this morning, I found something much better. Try this app: https://github.com/kcrawford/dockutil


If you did want to do it yourself, avoid AppleScript. That is for end users. If you are doing this quick-n-dirty from a shell script, use the “defaults” tool as in this not-so-great example. Make sure to run “killall cfprefsd” after stuffing values in someone else’s preferences.


This is still an incomplete solution. Hacking up the Dock might prevent problems in some cases. It might also stop working in a few weeks. But otherwise, there is no support in the operating system for multiple versions of the same app. There are many ways to launch an app (or do anything else to it). When you have multiple versions of an app, the app that gets picked is not defined. It could be any one. Furthermore, since the operating system fundamentally doesn’t support this, and it is driven by Spotlight, you don’t even have a guarantee of selecting the correct app even if you double-click on a specific version. This is part of Apple’s black box. Be clever at your peril.


So, if you find yourself looking for ways to hack up the Dock, I can assure you that you are doing it wrong. My official recommendation is to look for a better way to accomplish this. If you don’t want to modify the app itself, use something like git or dmgs to store different versions while having only one version present on the system.

Apr 4, 2022 6:38 AM in response to etresoft

"This is a user-to-user support forum."

I posted here because it's where I found the original identical question, and the answer that worked at the time but no longer does. I usually post on macscripter.net, which is aimed at developers. Looks like I should have posted there.


I'm aware of dockutil, which is great, but would involve installing it on a hundred users systems, I'd like to avoid that kind of dependency.


I had already seen the linked StackOverflow page, but that's about adding items to the Dock, which I can already do. Putting the correct version of the app in the dock is no problem, it's getting the old one out that's a problem.


I develop for prepress art. Most of our code base is Applescript... all the apps that I'm deploying here that I need to add/remove from the dock are Applescript. So I don't think I need to avoid it here.


The different versions of the apps are code signed and have unique bundle ID's. This situation happens all the time - for example, many users install multiple versions of Adobe Apps simultaneously, and Adobe's Creative Cloud app for managing applications lets you do this no problem, it's the default when installing a new app not to remove the old version. It's not treated as an exception at all. It is extremely common for developers and in many cases even for users to have multiple versions of the same app installed. MacOS's gatekeeper does get horribly confused when these apps are not code signed and/or don't have unique bundle ID's. Spotlight, of course, will do whatever, it's just a search tool. But I don't think it' accurate when you say "the operating system fundamentally doesn’t support this, and it is driven by Spotlight, you don’t even have a guarantee of selecting the correct app even if you double-click on a specific version." The operating system is driven by spotlight? You don't get the version of an app you double click? Those are not accurate in my experience.


If you look at the dock plist I'm trying to modify here, it keeps track of the app the dock button connects to by its path. Not bundle ID or application name, or anything else that can get confused between versions.


We do use git to store different versions of the code. GIT is not a deployment mechanism. You don't put your end users on git and deploy applications to git repositories, git is for managing code.


"if you find yourself looking for ways to hack up the Dock, I can assure you that you are doing it wrong" OK, so most major developers, like Adobe, Microsoft, and of course Apple are doing it wrong, because many of their apps add themselves as persistent to the dock when installed. But maybe removing old versions isn't standard. Unless they're uninstalled, but I assume that's MacOS, not the installer, automatically removing things that are no longer present.


I'll keep looking.

Apr 4, 2022 4:23 PM in response to t_spoon

Your use case is pretty specific, and atypical, meaning there may be no simple way to achieve it.


There are also some nuances that you understand (e.g. your user mentality, requirements, etc.), which are sometimes hard to translate online.


That said, from reading the posts, it sounds like what you want can be done via some kind of managed device model. There are several MDM products on the market that can manipulate the dock (pre-populate the dock and override user settings.


One that specifically talks about Dock management is Kandji: https://support.kandji.io/custom-dock

Removing an application from being persistent in the dock programatically

Welcome to Apple Support Community
A forum where Apple customers help each other with their products. Get started with your Apple Account.