How to add a custom badge to an app icon in the dock

I would caution against editing the info.plist in any application bundle, as it risks breaking file and value references that allow the application to operate. Editing the icon file in the Resources folder of the application bundle is a safer option.

Neither are a good idea. The former is going to invalidate the code signature, and as checks get tighter in the OS, the latter will too. It risks making an app unusable.

Good to know. I presume this goes for editing any file resource in an app bundle, be it a sound file, a jpeg, or what not ? Basically, I’m interpreting this to mean “leave the entire contents of an app bundle alone,” is that fair to say ?

Exactly.

Yes, but we will not edit the original icon itself. We will edit 1 dictionary key value of Info.plist. That is, we change only the link to the icon that we need. And that is temporary. Is it really that dangerous? After all, each application is an object with settings, and not some untouchable stone from Mecca

I’m not 100% sure, but logically, we could add another icon to the existing ones in the Resources folder and refer to it from the Info.plist if necessary.

One of the uses an app’s Info.plist file these days is to declare up-front several privacy related values. Allowing the file to be modified undermines that.

I know that there are applications that change the icons of files and folders to more beautiful ones. I do not know if there are any applications that change application icons … If they exist, how do they do it?

HERE is example of doing that

That is not actually changing the app’s icon – it’s just changing how it appears on your Mac. You can do it AppleScript:

use AppleScript version "2.5" -- 10.11 or later
use framework "Foundation"
use framework "AppKit"
use scripting additions

set picFile to choose file of type {"public.image"} with prompt "Choose an image file"
set theApp to choose file of type {"app"} with prompt "Choose the app to apply it to"

set theImage to current application's NSImage's alloc()'s initWithContentsOfURL:picFile
set ws to current application's NSWorkspace's sharedWorkspace()
ws's setIcon:theImage forFile:(POSIX path of theApp) options:0

The app itself will be completely unchanged.

I think this is what is needed in this case.

Will this update the appearance of the app in the dock (whether it’s currently running or not)? My experience with changing icons using the get info window is that you have to remove the app from the dock and re-add it.

OK, I just tried this out, but without the prompts (which defeat my purpose).

use AppleScript version "2.5" -- 10.11 or later
use framework "Foundation"
use framework "AppKit"
use scripting additions

set picFile to alias "Macintosh HD:Users:<my_username>:.slack_icons:slack.icns"
set theApp to alias "Macintosh HD:Applications:Slack.app"

set theImage to current application's NSImage's alloc()'s initWithContentsOfURL:picFile
set ws to current application's NSWorkspace's sharedWorkspace()
ws's setIcon:theImage forFile:(POSIX path of theApp) options:0

I encountered 2 problems.

  1. As I suspected, the app’s icon update does not get reflected in the dock (until I do something like “right-click-Options…->Show in Finder”).
  2. Script Editor won’t let me save the script with the error “The Document “Untitled.scpt” could not be saved as “clearSlackStatus.scpt”. C and Objective-C pointers cannot be saved in scripts. Compiling the script will reset property values and may resolve this issue.”

I’m sure you would have a ready solution to item 2, b ut I’m not familiar enough with AppleScript to know how to do that.

Regarding item 1, I still have to perform:

[format]rm -f /var/folders///*/com.apple.dock.iconcache
killall Dock[/format]

To make the change effective.

What a ridiculous work-around. I was able to save the script by creating a new empty script, saving it, pasting the code over from the script I couldn’t save, and then save it again. WTH?

You can save script with pointers using Script Debugger instead of Script Editor

I’ve noted that:

[format]rm -f /var/folders///*/com.apple.dock.iconcache[/format]

Removes the unread mail badge… so I’d still like to know how this update can be reflected in the icon in the dock…

That’s correct.

You’ve just pasted the solution: “Compiling the script will reset property values”.

I doubt that it can. The dock icon belongs to the app, not you.

No you can’t – scripts can’t be saved when top-level variables contain pointers, regardless of the editor. The solution is to re-compile, so the saved variables have no value.

But you can avoid the problem using Script Debugger, by turning off Persistent Properties.

If so, can I assign the missing value to the properties at the end of the script and achieve the same effect as recompilation?

Yes. But it’s not just properties – it’s all top-level variables that contain pointers.

Another solution, unless properties and/or globals are absolutely necessary in a running script (which I find they rarely are), is to make all the variables local, and therefore non-persistent, by putting the top-level run code into an ordinary handler:

use AppleScript version "2.5" -- 10.11 or later
use framework "Foundation"
use framework "AppKit"
use scripting additions

main() -- The sole instruction in the implicit run handler.

on main()
	set picFile to alias "Macintosh HD:Users:<my_username>:.slack_icons:slack.icns"
	set theApp to alias "Macintosh HD:Applications:Slack.app"
	
	set theImage to current application's NSImage's alloc()'s initWithContentsOfURL:picFile
	set ws to current application's NSWorkspace's sharedWorkspace()
	ws's setIcon:theImage forFile:(POSIX path of theApp) options:0
end main

I assumed I was implying that by pasting so obvious a fix, that it didn’t work. However, given my interactions with others online (and my parents), I realize I should have explicitly stated that I did compile and I still could not save and got the same error.