Changing icons dynamically for signed and notarized apps

We distribute our app externally to the users and not through the App Store. Our app is built and uploaded on our servers. We generate the app's configuration (different for each customer) on our servers and then package the configuration with the app. App is then signed and distributed to the end-users.

One of the configuration items is the app icon, which is placed in the apps /Contents/Resources directory.

With notarization being an asynchronous process, we need to provide a signed app for which the resources can't be altered as it would break the signing. Looking for solutions to change the app icon dynamically without breaking the app signature.

Solutions tried:

1. Modify the Icon file field in the app's info.plist with the URL of the icns file - Doesn't work and the icon doesn't change. Also breaks the signing as info.plist is inside the app.

2. Change the icon in the resources folder - Breaks signing as we have changed the contents inside the app.


Any suggestions on how this can be achieved?

Replies

How about a custom icon? That's the kind you can paste into the Finder Get Info panel. The icon is stored in a file named Icon\r (where \r is the hex 0D character) inside the app package, but not in the Contents folder. There is also a bit set in the com.apple.FinderInfo extended attribute on the application package.

Thanks for trying to help out!


I seem to be mission some key things from your suggestions though.

a) the icon\r file - Couldn't find it for my app or a few other apps I tried. This should be alongside the Contents folder? Tried looking for hidden files and directories as well, but no luck.

b) The com.apple.FinderInfo xattr - Tried setting the finderinfo attribute using

 xattr -w com.apple.FinderInfo <iconFile.icns> <appName.app>/

But that only gives me a "[Errno 34] Result too large" error. What am I missing?

the icon\r file - Couldn't find it for my app or a few other apps I tried.

Right. That file only exists after you give the app a custom icon. Consider this:

  1. Look at an app prior to adding a custom icon:

    $ # No Icon\r file...
    $ 
    $ ls -lh EagleFiler.app
    total 0
    drwxr-xr-x  10 quinn  wheel   320B 26 Jun 14:55 Contents
    $
    $ # No Finder info...
    $ 
    $ xattr -l EagleFiler.app

    .

  2. In the Finder, paste a custom icon on to the app.

  3. Look at the app again:

    $ # Look ma! an Icon\r file...
    $ 
    $ dir EagleFiler.app
    total 1952
    drwxr-xr-x  10 quinn  wheel   320B 26 Jun 14:55 Contents
    -rw-r--r--@  1 quinn  wheel     0B  9 Aug 08:45 Icon?
    $
    $ # And Finder info...
    $
    $ xattr -l EagleFiler.app
    com.apple.FinderInfo:
    00000000  00 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00  |................|
    00000010  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  |................|
    00000020

    .

This speaks to one of the problems with this technique, namely that there’s no good way to set a custom icon on a file. In theory you could do with this

NSURLCustomIconKey
but, as far as I know, this is not implemented.

So, to set this up you’d need to:

  1. Write the

    Icon\r
    file using a file system API.
  2. Set the Finder info flag (

    kHasCustomIcon
    ) directly.
  3. Figure out a way to get the Finder to recognise the change.

With regards step 2, the APIs I’d use for doing this (specifically,

FSSetCatalogInfo
) have all been deprecated without a replacement (with regards the Finder info) because Finder info is a deprecated concept in general. You’ll have to to use
setxattr
. You can use the
FolderInfo
and
ExtendedFolderInfo
structures in
Finder.h
to construct the value you set.

With regards step 3, the Finder might just notice this change on its own. If not, there have been various APIs you can call to give it a nudge, but I’ve long since forgotten all the details )-:

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Hello Quinn,


We are also looking for a non-depricated replacement for FSSetCatalogInfo. What are your thoughts on using getattrlist and setattrlist? One can access the Finder Info using the common attribute ATTR_CMN_FNDRINFO. It appeared to work when I tested this a while back but I could not find any information on whether this is could (should?) be used as a replacement for FSSetCatalogInfo.

Ah, yeah, I forgot about

ATTR_CMN_FNDRINFO
. That’s a perfectly reasonable way to work with Finder info as well. I don’t have a strong preference for this or the extended attribute approach.

Just for my own curiosity, where are you doing with Finder info? The originator of this thread has very limited goals (setting

kHasCustomIcon
). Are you doing just that? Or something more extensive?

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Hello Quinn,


Like the original poster we are just setting kHasCustomIcon. In our case we are adding a custom icon to a disk image volume that we create in code. We actually filed a bug (FB5771677) in 2016 against the non-functional NSURLCustomIconKey.


Thanks

We actually filed a bug (FB5771677) in 2016 against the non-functional

NSURLCustomIconKey
.

Thanks for that. Alas, this issue is ensnared in the bigger issue of how to decouple custom icons from the Resource Manager (r. 6508029)-:

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

If the configuration is packaged within the app, wouldn’t changing the configuration also changes the bundle signature?


If that’s the case and there is a 1:1 relationship between a configuration and an app icon, wouldn’t changing the app icon resource as part of the build/notarization process would be better?


Remember that you’ll probably need unique bundle identifiers as well since the configuration is placed inside the app’s bundle (hence part of “the app”).

Changing

Info.plist
properties, like
CFBundleIconFile
, would definitely break the seal on the app’s code signature, which is why discussion on this thread has focused on custom icons.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"