Modify notification center preferences, widgets, etc from the command line

MrP
Contributor III

Does anyone know if there is a way to do this in Yosemite? I ran opensnoop while changing preferences to see if I could figure out where it saves them to but didn't see anything being modified.

I'd like to programmatically disable notifications at the lock screen for all items for all of our users. In Mavericks I had disabled Notification center. Being that JAMF moved their agent notifications to using it we no longer see those:-(. Hoping Yosemite is a little more configurable.

1 ACCEPTED SOLUTION

jacob_salmela
Contributor II

@Dickson : @gregneagle 's most recent addition now allows you to change the settings you want. Here are a few examples:

Show iCal Notifications on the lock screen

NCutil.py --show-on-lock-screen true com.apple.iCal

Disable the badge app icon for Messages

NCutil.py --badge-app-icon false com.apple.iChat

Disable the sound for TextWrangler

NCutil.py --sound false com.barebones.textwrangler

Set the amount of recent Notifications to show to 20 for Dropbox

NCutil.py --show-in-notification-center 20 com.getdropbox.dropbox

View solution in original post

36 REPLIES 36

jacob_salmela
Contributor II

NCutil.py can't change that setting quite yet, but it can do a lot. Special thanks for @gregneagle for all his contributions!

Add apps

NCutil.py -i com.noodlesoft.HazelHelper
NCutil.py --insert com.noodlesoft.HazelHelper

Remove apps

NCutil.py -r com.barebones.textwrangler
NCutil.py --remove com.barebones.textwrangler

Adjust Alert Duration (Alerts, Banners, or None)

NCutil.py -a com.apple.Safari alerts
NCutil.py -a com.apple.reminders banners
NCutil.py --alert-style com.apple.appstore none

Get Current Settings
You can find out what the app's current settings are:

NCutil.py --get-info com.teamviewer.TeamViewer

which will return something like this:

Notification Center settings for TeamViewer.app:
    TeamViewer.app alert style:        Banners
    Show notifications on lock screen: Yes
    Show in Notification Center:       5 Recent Items
    Badge app icon:                    Yes
    Play sound for notifications:      Yes

Get Current Alert Setting

NCutil.py -g com.teamviewer.TeamViewer
NCutil.py --get-alert-style com.teamviewer.TeamViewer

davidhiggs
Contributor III

nice work @jacob_salmela ! I put a feature request in with Apple to do this kind of stuff recently. This is great for the meanwhile though, will try it out thanks!

jacob_salmela
Contributor II

@Dickson : @gregneagle 's most recent addition now allows you to change the settings you want. Here are a few examples:

Show iCal Notifications on the lock screen

NCutil.py --show-on-lock-screen true com.apple.iCal

Disable the badge app icon for Messages

NCutil.py --badge-app-icon false com.apple.iChat

Disable the sound for TextWrangler

NCutil.py --sound false com.barebones.textwrangler

Set the amount of recent Notifications to show to 20 for Dropbox

NCutil.py --show-in-notification-center 20 com.getdropbox.dropbox

MrP
Contributor III

Wow. Thanks @gregneagle and Jacob! Is there a way to list the current apps so I can script a loop to apply the settings to all?

jacob_salmela
Contributor II
NCutil.py -l

but be cautious of the SYSTEM_CENTER items.

MrP
Contributor III

Perfect. You guys rock!

dgkanavias
New Contributor

In order to run this file through a script (at a Policy ) , we have to do something different or just : python NCutil.py --show-on-lock-screen true com.apple.iCal ???

gforsyth
New Contributor III

This is awesome. Any thoughts on how to adjust the default notifications on lock screen. Notification Center defaults all apps to show notifications on lock and I would like to change that if possible.

Mark_Stohel
New Contributor

I'm getting error messages when I try this. I'm trying to disable the lock screen notification for Jabber, and I created a script with the following:

python /Library/Company/NCUtil.py --show-on-lock-screen false com.cisco.Jabber

created a policy to run that script, and it gives error messages:

Executing Policy Change Jabber Lock Screen Notification Running script Change Jabber Lock Screen Notification... Script exit code: 1 Script result: Traceback (most recent call last): File "/Library/Company/NCUtil.py", line 605, in main() File "/Library/Company/NCUtil.py", line 595, in main options.show_on_lock_screen[0], options.show_on_lock_screen[1:]) File "/Library/Company/NCUtil.py", line 401, in set_show_on_lock_screen if not bundleid_exists(bundle_id): File "/Library/Company/NCUtil.py", line 153, in bundleid_exists conn, curs = connect_to_db() File "/Library/Company/NCUtil.py", line 69, in connect_to_db conn = sqlite3.connect(nc_db) sqlite3.OperationalError: unable to open database file Error running script: return code was 1.

It worked on one machine that I had logged in, but on all other test machines with me logged in or other employees, it failed with the above errors. Any ideas?

bearzooka
Contributor

Hey, Mark.

Did you ever get this to work? I'm having the exact same issue when calling this script from a Casper Policy.

Thanks!

bearzooka
Contributor

Okay, I figured out that the problem is that JSS scripts are run as a different user and therefore it doesn't have permission to open the db for the current user… Or the other way around. Thing is, if I try to run this remotely, it fails.

MrP
Contributor III

@bearzooka @Mark.Stohel

#!/bin/sh


IFS=$'
'
user=`ls -l /dev/console | cut -d " " -f 4`

a=`sudo -u $user /usr/local/bin/NCutil.py -l | grep -v "SYSTEM_CENTER"`
for i in $a;
do 
     #echo "User:Disabling show on lockscreen notify for: $i"
     sudo -u $user /usr/local/bin/NCutil.py --show-on-lock-screen false $i
done

bearzooka
Contributor

Thanks, @MrP.
I did something similar but using the $4 parameter.

MrP
Contributor III

@jacob_salmela, @gregneagle In the script I modified the following line which allowed it to run on 10.12, however the option "--show-on-lock-screen" has no affect. Any chance you can updated it for 10.12?

elif osx_major == '10.10' or osx_major == '10.11':

to:

elif osx_major == '10.10' or osx_major == '10.11' or osx_major == "10.12":

jacob_salmela
Contributor II

I'm a bit busy with other projects at the moment, but if someone makes me a pull request, I can review it. I'm guessing Apple changed something slightly in their DB structure. They did a similar thing with TCC.db.

milesleacy
Valued Contributor

Has anyone used this successfully on 10.11.6 (15G1217)?

I get the following output...

bash-3.2# /.../.../.../NCutil.py -l
Traceback (most recent call last):
  File "/.../.../.../NCutil.py", line 605, in <module>
    main()
  File "/.../.../.../NCutil.py", line 572, in main
    list_clients()
  File "/.../.../.../NCutil.py", line 99, in list_clients
    conn, curs = connect_to_db()
  File "/.../.../.../NCutil.py", line 69, in connect_to_db
    conn = sqlite3.connect(nc_db)
sqlite3.OperationalError: unable to open database file
bash-3.2# /.../.../.../NCutil.py -a com.jamfsoftware.Management-Action alerts
Alert style must be one of: none, alerts, banners.

EDIT: Same results with 10.10.5 (14F2109)

milesleacy
Valued Contributor

Note...

There is a Notifications payload in the Apple Configurator 2 application (pictured). A profile that contains this payload can be applied to a Mac running macOS Sierra (applying the profile to El Capitan or Yosemite yields no results). The result is similar to an MCX setting applied at the user level with an "often" frequency, that is the setting applies at every login, but can be changed during the user's session.

I am making the assumption that this is new behavior that is making its way into macOS (yes, I know I could be wrong) and as such using it.

Since Yosemite and El Capitan are relatively static at this point and will be supported for roughly another six months and year and a half, respectively, and this solution had worked in those OS versions before, I was hoping to use the script on my Yosemite & El Capitan Macs.

My goal here is to find a way to set notifications from the Jamf Management Action application to use the "alerts" alert style because they are persistent until interacted with - thus users have less room to claim they didn't know about a change.

44c308331f8c47528a4c34a63473d2a1

myronjoffe
Contributor III

@milesleacy Did you get this to work using profiles?

myronjoffe
Contributor III

@milesleacy Did you get this to work using profiles?

milesleacy
Valued Contributor

@myronjoffe Yes, through trial and error, capturing manually-set values in plists, and then adding those values to a custom payload.

bearzooka
Contributor

Revisiting this topic, but now for High Sierra… The Notifications db structure seems to have changed dramatically and I haven't been able to find a table with the Flags column or something similar. Maybe @jacob_salmela has some pointers on how to find that info again.

Also, I've tried using Apple Configurator 2, as @milesleacy suggests, and every Config Profile I try to install marks the payload (i.e. Notifications settings) as being iOS only and does pretty much nothing.

Thanks for your input!

tlarkin
Honored Contributor

Has anyone here look at Yo? It does notification style dialog boxes

lsegura
New Contributor II

Hi @jacob_salmela any option to disable "show notifications on lock screen" in Sierra?

jacob_salmela
Contributor II

Sorry; it's been a while since I've worked on the project...I'll take a look and get back to you

bearzooka
Contributor

Hey, @milesleacy. I've been trying to hide the notifications in the lock screen using a Config Profile and haven't had any luck. Do you have by any chance an example plist that you've used as a custom payload?

Whatever I try keeps installing empty MCX config profiles that obviously don't work as expected.

Thanks in advance.

bearzooka
Contributor

In case anyone is still interested, I'm testing the following approach that uses PlistBuddy and, since we're only changing the plist, implies that we run this script on a daily basis.

#!/bin/bash

#List of the name of the bundles that need to be configured. Set to your needs.
bundlesToConfigure=('com.apple.FaceTime' 'com.apple.iCal' 'com.apple.FaceTime' 'com.apple.gamecenter' 'com.apple.mail' 'com.apple.iChat' 'com.apple.reminders' 'com.apple.Safari' 'com.apple.iTunes')

#Location of the notification center preferences plist for the current user
notificationsPLIST="$HOME/Library/Preferences/com.apple.ncprefs.plist"

#Count of the bundles existing in the plist
count=$(/usr/libexec/PlistBuddy -c "Print :apps" "$notificationsPLIST" | grep "Dict"|wc -l)

#Substracting one to run in a for loop
count=$((count - 1))

for index in $(seq 0 $count); do
    #Getting each bundle id with PlistBuddy
    bundleID=$(/usr/libexec/PlistBuddy -c "Print apps:$index:bundle-id" "$notificationsPLIST");

    #If the name of the current bundle is in our list of bundles to configure
    if [[ " ${bundlesToConfigure[*]} " == *" $bundleID "* ]]; then

        #Use PlistBuddy to set the value of flags to 4110 (hide in lock screen)
        /usr/libexec/PlistBuddy -c "Set :apps:${index}:flags 4110" "$notificationsPLIST"

    fi
done

exit 0

Of course, some work could be added to customize or combine the flags.

EDIT:

The values in the plist do change, but the configuration and the NC preference pane don't.

2nd EDIT:

After a reboot (or maybe only a new log in) the settings are in place.

MrP
Contributor III

Incorrect information deleted.

bearzooka
Contributor

Thanks, @MrP, I'll try that out ASAP.

MrP
Contributor III

@bearzooka Changes to that plist under 10.13.1 do not stay across reboots, restart of the NotificationCenter, usernoted, or opening of the preferences panel for NC. All of those actions flip the values in the plist back to what they were before the script ran. The "app_info" table of my NC db has all flags set above 4096(the required value for disabling notifications at the lock screen), and is missing some of the apps, so I suspect that table is no longer in use. I couldn't find anything in the "db2" db for NC related to configurations. It appeared to be a staging area for triggers and notification states. I'm at a loss as to how to programmatically change this other than using an MCX and hoping users do not add other notification objects.

MrP
Contributor III

@bearzooka After a reboot of my test system the script works fine. I have no idea why my settings were getting clobbered yesterday by a restart of the NC processes. Anyway, I made some changes to your script that you or others may find useful.
1. It's designed to run as root/via the jamf agent
2. The bundlestoconfigure line pulls a list of all current 'bundles' and excludes system bundles which are not user configurable. This mitigates having to edit a static list, should you prefer it. Note that this required modifying the 'if' line as well to remove the spaces between the criteria and the quotes.
3. For whatever reason echo on the 'apps' count line was getting binary data from plist buddy on my system. I suspect you were working with an xml plist, as opposed to a binary. I had to split the line into two in order to get the data I wanted. This also could have been related to whatever was keeping the changes from taking before my reboot. shrug
4. Rather than statically setting the flags as 4110, it adjusts the flags dynamically by adding 4096 as needed, which is the value for disabling notification on lockscreen. This way no other check boxes/preferences are modified except that one.
5. If changes are made, it restarts the NotificationCenter and usernoted processes so they take effect.

Thanks again for the great script. Took most of the work out of it for me!

#!/bin/bash

IFS=$'
'

user=`ls -l /dev/console | cut -d " " -f 4`

#Location of the notification center preferences plist for the current user
notificationsPLIST="/Users/$user/Library/Preferences/com.apple.ncprefs.plist"

#List of the name of the bundles that need to be configured. Set to your needs.
#bundlesToConfigure=('com.apple.FaceTime' 'com.apple.iCal' 'com.apple.FaceTime' 'com.apple.gamecenter' 'com.apple.mail' 'com.apple.iChat' 'com.apple.reminders' 'com.apple.Safari' 'com.apple.iTunes')
# Get list of all user manipulatable notification center objects 
bundlesToConfigure=`defaults read $notificationsPLIST  | grep bundle-id | awk -F " '{print $4}' | grep -v "_SYSTEM_CENTER_"` 


#Count of the bundles existing in the plist
apps=`/usr/libexec/PlistBuddy -c "Print :apps" "$notificationsPLIST"`
count=$(echo "$apps" | grep "bundle-id"|wc -l)

#Substracting one to run in a for loop
count=$((count - 1))

change=0
for index in $(seq 0 $count); do
    #Getting each bundle id with PlistBuddy
    bundleID=$(/usr/libexec/PlistBuddy -c "Print apps:$index:bundle-id" "$notificationsPLIST");

    #If the name of the current bundle is in our list of bundles to configure
    if [[ "${bundlesToConfigure[*]}" == *"$bundleID"* ]]; then
        flag=`/usr/libexec/PlistBuddy -c "Print apps:$index:flags" "$notificationsPLIST"`
        echo Current value:  $index:$bundleID $flag
        if [ $flag -lt 4096 ]; then
            echo "  Flag is less than 4096.  Adding 4096 to disable notification/preview on lockscreen."
            flag=$((flag + 4096))
            change=1
            sudo -u $user /usr/libexec/PlistBuddy -c "Set :apps:${index}:flags ${flag}" "$notificationsPLIST"
            flag=`/usr/libexec/PlistBuddy -c "Print apps:$index:flags" "$notificationsPLIST"`
            echo New Value: $index:$bundleID $flag
        fi
    fi
done

# Restart notification center to make changes take effect.
if [ $change == 1 ]; then echo "Changes made.  Restarting Notification Center for them to take effect.";killall sighup usernoted;killall sighup NotificationCenter; fi

exit 0

bearzooka
Contributor

Thanks, @MrP. I like the tweaks that you're proposing. I will test them out as soon as I am done with some other to-do's.

MrP
Contributor III

I've determined what was providing inconsistent results. If I run either of our scripts as the logged in user, directly(not using sudo -u or launchctl asuser), the settings are kept/applied after a restart of the NC binaries. If run my script as root, even though I am applying settings using "sudo -u", and I've tried "launchctl asuser", the plist is updated, but then over-written with the old settings when the NC binaries are restarted. This happens 19 out of 20 times. Once in a while the settings will stick when running the script as root/under the jamf agent. I have no idea what condition takes place that allows the settings to be applied so randomly. I've tried killing the binaries as the user/notroot using sudo and launchctl to see if that made a difference and it did not. I've monitored the plist ownership and permissions thinking that perhaps when running the script as root that it was flipping permissions causing NC to buck, but they do not change when the file is modified.

If anyone has a solid idea as to what is happening in the different user contexts to cause this behavior I'd like to get a better understanding. As is I cannot find any reason for the different behavior given that I've tried doing everything as the user from root under "sudo -u" or "launchctl asuser".

I see two options. Deploy the script and a launch agent to run it as the user, or run the script regularly across all user directories, using existence of the list in the user directory as criteria to run it, whether or not any user is logged in. This would set it for all users profiles on the system, and presumably since the user wouldn't be logged in at some point during one of the iterations, it would eventually successfully lock down the settings. The first option is more sound but I really hate deploying launchagents/daemons because that means just another workflow to document, and they don't give me any feedback in the JSS logs like running from a policy would. Also given that this is a security concern, I don't want to enforcement to be something users has permission to unload should they want to.

Jason
Contributor II

I know this is a pretty old thread now. But on Mojave i'm not sure if this works 100% any more. The previous logic to check for 4096+ doesn't seem to work any more. Going to look at the data some more, but it looks like i have 12,622 now with everything checked except for notifications on the lock screen and 8206 for everything checked. Probably just needs a value update, but i'm not sure if anyone else has more data already.

Thanks

joepopson
New Contributor III

Bump on this anyone? I'm also having some issues setting notifications settings to be set to not show lock screen notifications for certain apps, or even all apps would do.

Please advise!
Thanks

Joe

prl
Contributor

@joepopson looks like someone posted here: https://www.jamf.com/jamf-nation/discussions/9630/disabling-show-notifications-on-lock-screen-in-system-prefs#responseChild178859

roybrian
New Contributor

This thread might be old but setting up notification settings for different apps on Mojave is still a chore.
I’ve been having success with the following script:

#!/bin/sh

#Location of the notification center preferences plist for the current user
    notification_plist="$HOME/Library/Preferences/com.apple.ncprefs.plist"

    #Count of the bundles existing in the plist
    count=$(/usr/libexec/PlistBuddy -c "Print :apps" "${notification_plist}" | grep -c "bundle-id")

    for ((index=1; index<"${count}"; index++)); do
        #Getting each bundle id with PlistBuddy
        bundle_id=$(/usr/libexec/PlistBuddy -c "Print apps:${index}:bundle-id" "${notification_plist}");

        case "${bundle_id}" in
            # leave as is
            "com.apple.iChat"|"com.apple.mail"|*"_SYSTEM_CENTER_"*|*"_WEB_CENTER_"*|"com.apple.appstore"|"com.apple.TelephonyUtilities") ;;

            # Leave as alerts but don't show on lock screen.
            # To show on lock screen, but preview only when unlocked, use flags "22" (DOESN'T WORK)
            "com.apple.reminders"|"com.apple.iCal")
            /usr/libexec/PlistBuddy -c "Set :apps:${index}:flags 12310" "${notification_plist}";;

            # Disable completely
            "com.flexibits.fantastical2.mac")
            /usr/libexec/PlistBuddy -c "Set :apps:${index}:flags 28993" "${notification_plist}" ;;

            *)
            # 3rd party apps
                # set to banners, don't show on lock screen
                    # for apps that default to "Alerts" (1Password, Dropbox), use flags "12366"
                    # for apps that default to "Banners", use flags "12302"
                # To show on lock screen but preview only when unlocked (DOESN'T WORK)
                    # for apps that default to "Alerts" (1Password, Dropbox), use flags "78"
                    # for apps that default to "Banners", use flags "14"

                # Getting current value of "flags"
                flag=$(/usr/libexec/PlistBuddy -c "Print apps:${index}:flags" "${notification_plist}")

                    # For 3rd party apps that default to "Alerts" (1Password, Dropbox)
                    if [[ "${flag}" -eq 8214 ]] || [[ "${flag}" -eq 8270 ]]; then
                        /usr/libexec/PlistBuddy -c "Set :apps:${index}:flags 12366" "${notification_plist}"

                    # For 3rd party apps that default to "Banners"
                    elif [[ "${flag}" -eq 8206 ]]; then
                        /usr/libexec/PlistBuddy -c "Set :apps:${index}:flags 12302" "${notification_plist}"

                    # if an app was already set with proper values
                    elif [[ "${flag}" -eq 12366 ]] || [[ "${flag}" -eq 12302 ]]; then
                        :
                    else
                    # for undocumented cases
                    echo -e ${red}"An unknown flags value ${yellow}(${flag}) ${red}has been encountered for ${yellow}${bundle_id}${red}, manual check might be necessary."${nc}
                    fi
            esac
        done

    # Restart notification center to make changes take effect.
    killall sighup usernoted
    killall sighup NotificationCenter

I must admit, I didn’t get the whole “flags” thing completely figured out yet.
Moreover, I would ideally like that for every app, the:
“Show notification preview” would be ticked, but always with the “Show notification preview” option set to “when unlocked”. Presumably, the correct flag for this behavior — along with the other notification settings — is “22” (based on Apple’s Mail and Messages apps, whose default behavior is the one I would like to implement in nearly all of my apps).
However, using “22” in my script never works. Curiously enough, setting the “Show notification preview” to “when unlocked” through the GUI doesn’t work either! After logging out or restarting, that setting is always switched back to “always”, so I suspect this is a bug. Has anyone else experienced that?

Thanks!