Forcing screen saver with script

franrayner
New Contributor II

Hi,
I am required to force all users screen saver to display a collection of images as supplied by our IT Security department, and I'm trying to work out the best way to achieve this.
I have a a policy that successfully copies the screen savers to the Macs ok. And I have a script stolen from another discussion that works, see below. But only if I manually trigger it via Casper remote. I have a policy that should trigger this at login/ ongoing and it reports that it runs successfully but it doesn't. Not sure if this is most efficient way of doing this as it runs every time any user logs in, repeatedly.
I was hoping there was a way via as configuration profile of adding the script but cant see a way to do this.

Anybody done this successfully please?
script...

!/bin/sh

Get user logged into console and put into variable "user"

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

sudo -u $user defaults -currentHost write com.apple.screensaver CleanExit -string "YES"
sudo -u $user defaults -currentHost write com.apple.screensaver PrefsVersion -int 100
sudo -u $user defaults -currentHost write com.apple.screensaver showClock -string "YES"
sudo -u $user defaults -currentHost write com.apple.screensaver idleTime -int 120
sudo -u $user defaults -currentHost write com.apple.screensaver moduleDict -dict moduleName -string "iLifeSlideshows" path -string "/System/Library/Frameworks/ScreenSaver.framework/Resources/iLifeSlideshows.saver" type -int 0
sudo -u $user defaults -currentHost write com.apple.screensaver tokenRemovalAction -int 0

sudo -u $user defaults -currentHost write com.apple.ScreenSaverPhotoChooser LastViewedPhotoPath -string ""
sudo -u $user defaults -currentHost write com.apple.ScreenSaverPhotoChooser SelectedFolderPath -string "/Users/Shared/Screensaver.secure"
sudo -u $user defaults -currentHost write com.apple.ScreenSaverPhotoChooser SelectedSource -int 3

sudo -u $user defaults -currentHost write com.apple.ScreenSaver.iLifeSlideShows styleKey -string "Classic"

sudo killall -hup cfprefsd

33 REPLIES 33

StoneMagnet
Contributor III

@franrayner You can't add a script to a configuration profile, but have you tried creating a Configuration Profile with a Custom Settings payload that has the ScreenSaver prefs set the way you want instead of trying to write them via a script?

P.S. My semi-daily PSA - If you want to paste code into a forum post either use the >_ icon above the response block to add a Markdown tag, or use a triple backtick (```) before and after your code so that it appears properly in your post.

franrayner
New Contributor II

Yes I would prefer to use the Configuration Profile method.
Please can you give me a clue on creating the custom payload for this as I have never done this before?

StoneMagnet
Contributor III

@franrayner You need to create a .plist with all of the settings you're trying to apply for each domain (the com.apple.screensaver, com.apple.ScreenSaverPhotoChooser, and com.apple.ScreenSaver.iLifeSlideShows domains based on your initial post). The easiest way to do that is to make the Screen Saver changes on a test machine then open the ~/Library/Preferences/ByHost/ directory and use /usr/bin/plutil -convert xml1 /path/to/file.plist to convert the binary .plist files you'll find there into the .xml format you'll need for the JSS.

Next create a Configuration Profile in your JSS that has a Custom Settings payload for each preferences domain (make sure the Preferences Domain entry for the payload is appropriate for the property list you upload for it). Scope the Configuration profile to some test machines and verify it does what you intend before deploying it to your production environment.

franrayner
New Contributor II

Great, let me give that a go, thanks very much for help.

talkingmoose
Moderator
Moderator

I think @StoneMagnet has given you the best advice. You can't enforce anything with a script, but you can enforce using a configuration profile. I'll add something else.

Because you already know the plist names and settings, you may find it easier to write these to plist files on your Desktop to avoid altering your own settings and make the files easier to find. For example, you already have this command:

sudo -u $user defaults -currentHost write com.apple.screensaver CleanExit -string "YES"

In Terminal, you could enter this to write to a file on your Desktop instead:

defaults write ~/Desktop/com.apple.screensaver.plist CleanExit -string "YES"

No need for sudo because you're writing to your own user space and just creating a new file. Repeat this with each of your commands and then you'll have clean plists you can upload to a Custom Settings payload in a new Configuration Profile. You'll get prompted to convert the files to XML during the upload. Just follow the instructions in red and you'll be fine.

franrayner
New Contributor II

Thanks, thats very helpful @talkingmoose, Ill give it a go.

franrayner
New Contributor II

Well not sure what I'm doing wrong...
The script as it is works and my problem remains as the best way to distribute to all user who login to the Macs.
So taking the commands from the script I created the 3 plists and converted them, uploaded them to JSS as custom payloads, and I know the configuration profile is working as I added in a message on login page and that shows, but the screen saver does not get set as in the payloads.
I'm wondering if the last line in script sudo killall -hup cfprefsd is required?

Any guidance would be appreciated please?

talkingmoose
Moderator
Moderator

Configuration profiles apply instantly when installed. They won't pay attention to cfprefsd.

Note that some screen saver settings are drop down menus. For example, if you look at Apple menu > System Preferences > Desktop & Screen Saver > Screen Saver, you'll see the Start After drop down menu only has a limited set of choices. If you were to set the time to "15 minutes" in your profile, you won't see that reflected here. But you should see the menu dimmed and inaccessible if it's being managed.

Be sure the domain names in your configuration profile also exactly match the plist file names (without the .plist) as you'd see them in your preferences folders.

Consider posting your plists here (please format them using the code tool for easier reading). Maybe someone will see what's causing the issue.

joshuasee
Contributor III
I'm wondering if the last line in script sudo killall -hup cfprefsd is required?

Given that you're using the defaults command, an Apple designed and approved tool, to do the property list tweaking rather than editing XML, restarting cfprefsd should not be required.

BTW, opening /System/Library/Frameworks/ScreenSaver.framework/Versions/Current/Resources/ScreenSaverEngine.app is still starting the screen saver for me in Sierra.

Also, is a screensaver the best route for displaying this information rather than a PolicyBanner.rtfd ?

EUC600
New Contributor III

Is iLifeSlideShows.saver gone in Mojave 10.14.2? If so then did a different file replace it?

I'm unable to see it in /System/Library/Frameworks/ScreenSaver.framework/Resources/iLifeSlideshows.saver anymore.

discounteggroll
New Contributor III

updating from 10.14.1 to 10.14.2 led me to this page, my custom screensaver is now broken because of the omission of the /iLifeSlidesshows.saver file.

Has there been any progress regarding gaining this functionality back?

jlang_remedy
New Contributor III

This script breaks in 10.14.2 due to the path of /System/Library/Frameworks/ScreenSaver.framework/Resources/iLifeSlideshows.saver changing. I've edited the script to check the OS version is greater or equal to 10.14.2, and and use the new path of /System/Library/Frameworks/ScreenSaver.framework/PlugIns/iLifeSlideshows.appex if so. See edited version below.

#!/bin/sh
# Get user logged into console and put into variable "user"
user=`ls -l /dev/console | cut -d " " -f 4`
osMajor=$(sw_vers -productVersion | awk -F"." '{print $2}')
osMinor=$(sw_vers -productVersion | awk -F"." '{print $3}')


sudo -u $user defaults -currentHost write com.apple.screensaver CleanExit -string "YES"
sudo -u $user defaults -currentHost write com.apple.screensaver PrefsVersion -int 100
sudo -u $user defaults -currentHost write com.apple.screensaver showClock -string "NO"
sudo -u $user defaults -currentHost write com.apple.screensaver idleTime -int 120


if [[ $osMajor -eq 14 ]] && [[ $osMinor -ge 2 ]]; then

        sudo -u $user defaults -currentHost write com.apple.screensaver moduleDict -dict moduleName -string "iLifeSlideshows" path -string "/System/Library/Frameworks/ScreenSaver.framework/PlugIns/iLifeSlideshows.appex" type -int 0

        else

        sudo -u $user defaults -currentHost write com.apple.screensaver moduleDict -dict moduleName -string "iLifeSlideshows" path -string "/System/Library/Frameworks/ScreenSaver.framework/Resources/iLifeSlideshows.saver" type -int 0
fi


sudo -u $user defaults -currentHost write com.apple.screensaver tokenRemovalAction -int 0

sudo -u $user defaults -currentHost write com.apple.ScreenSaverPhotoChooser LastViewedPhotoPath -string ""
sudo -u $user defaults -currentHost write com.apple.ScreenSaverPhotoChooser SelectedFolderPath -string "/Users/Shared/Photos/"
sudo -u $user defaults -currentHost write com.apple.ScreenSaverPhotoChooser SelectedSource -int 3

sudo -u $user defaults -currentHost write com.apple.ScreenSaver.iLifeSlideShows styleKey -string "Classic"

sudo killall -hup cfprefsd

theguvnor
New Contributor III

@jlang_remedy Many thanks for the updated script, that's helped a lot in pointing me in the right direction.

Don't suppose you would have any simple way of enforcing the same screensaver to appear over the login window? Is the iLifeSlideshows method able to be used there, too?

My task is having a set of images, saved locally on the machine in the same way you've done, display as the screensaver over the login window rather than as the logged-in user :(

bruce-at-umass
New Contributor

I've got a set of iMacs running 10.13 in a student broadcast studio, some of which are within view of the cameras when they are doing a show. The instructor wants to be able to quickly trigger a screen saver with a single, static, non-moving image on the visible iMacs. As a test, when logged in using a local admin account, I set the screen saver to "Classic" mode and set the Source to a folder I created, inside of which is the image file. I also set a Hot Corner to trigger the screen saver. Works well and is very quick.

Is the script most recently posted by @jlang_remedy the best approach to get this screen saver working for all users, and will it handle the Hot Corner trigger?

daniel_green_ne
New Contributor

@bruce-at-umass We use this script and I am able to manually set the Hot Corners (one for display sleep and one for screensaver) and it works perfectly. I use this script along with a package of photos that are placed in the /Users/Shared folder and is set to run once a day per user. This makes it so that if I upload a new package of photos, it'll be pulled down the next day. Hope that helps and thanks to @jlang_remedy for the script!

theguvnor
New Contributor III

@daniel.green.nec I don't suppose you initiate that screensaver over the login window, too, by any chance (i.e. with no user logged in)? :) Looking for any way of doing that, otherwise I may just have to abandon the idea :(

Please see the separate thread I opened on the issue at https://www.jamf.com/jamf-nation/discussions/30715/custom-images-as-screensaver-at-the-login-window-lab-environment for more info.

aarmas
New Contributor

Hey Everyone!

Thank you for sharing this information as its been super helpful.

Im running into 1 issue - after I run the script via policy, everything seems to go through successfully but it seems as though the changes arent being applied.

I changed the timeout to 600 (10 minutes) and i can confirm its being change successfully as the output from (defaults -currentHost read com.apple.screensaver idleTime) comes out to 600. I tested changing to 300 and then re-ran the policy to make sure its changing but my machine still seems to go to sleep in under 5 minutes.

Does anyone have any idea what im missing here? We currently have a config profile for ScreenSaver set to 20 minutes, but I excluded myself from the profile so it shouldnt be conflicting correct?

arpierson
New Contributor III

I took a slightly different approach. Using this thread as a launching point (thanks @tfenna!) , I:

  1. Set the screensaver up how I wanted it on a test machine.
  2. Edited EffectDescriptions.plist located at /System/Library/PrivateFrameworks/Slideshows.framework/Versions/A/Resources/Content/ to make each image my organization wanted in the screensaver to stay on screen longer than the default 3 seconds. (You can do this by changing the value in JustASlide>mainDuration)
  3. Copied the three screensaver .plist files plus the EffectDescriptions.plist to a folder and packaged them up
  4. Created one policy in Jamf that runs once per computer to install both the image files that I previously packaged and the .plist files.
  5. Created a second policy that runs at login and every checkin that runs the script that I modified from the linked thread to copy the .plist files to their respective correct locations, names them properly based on the current user's UUID, and gives the user the correct permissions.

Here's how I modified the script to work in our environment:

#!/bin/bash

# Sets the variable to retrieve the Macs UUID
macUUID=`ioreg -rd1 -c IOPlatformExpertDevice | grep -i "UUID" | cut -c27-62`

# Remove the current plist files
rm /Users/$3/Library/Preferences/ByHost/com.apple.screensaver.$macUUID.plist
rm /Users/$3/Library/Preferences/ByHost/com.apple.ScreenSaverPhotoChooser.$macUUID.plist
rm /Users/$3/Library/Preferences/ByHost/com.apple.ScreenSaver.iLifeSlideShows.$macUUID.plist

cp /private/var/screensaver/com.apple.screensaver.x.plist /Users/$3/Library/Preferences/ByHost/com.apple.screensaver.$macUUID.plist
cp /private/var/screensaver/com.apple.ScreenSaver.iLifeSlideShows.x.plist /Users/$3/Library/Preferences/ByHost/com.apple.ScreenSaver.iLifeSlideShows.$macUUID.plist
cp /private/var/screensaver/com.apple.ScreenSaverPhotoChooser.x.plist /Users/$3/Library/Preferences/ByHost/com.apple.ScreenSaverPhotoChooser.$macUUID.plist
cp /private/var/screensaver/EffectDescriptions.plist /System/Library/PrivateFrameworks/Slideshows.framework/Versions/A/Resources/Content/EffectDescriptions.plist

# Gives the logged on user access to the SlideShow folder & plist files
chmod 755 /Users/$3/Library/Preferences/ByHost/com.apple.screensaver.$macUUID.plist
chmod 755 /Users/$3/Library/Preferences/ByHost/com.apple.ScreenSaverPhotoChooser.$macUUID.plist
chmod 755 /Users/$3/Library/Preferences/ByHost/com.apple.ScreenSaver.iLifeSlideShows.$macUUID.plist

killall cfprefsd

theguvnor
New Contributor III

@arpierson I don't suppose you initiate that screensaver over the login window, too, by any chance (i.e. with no user logged in)? :) Looking for any way of doing that, otherwise I may just have to abandon the idea :(

Please see the separate thread I opened on the issue at https://www.jamf.com/jamf-nation/discussions/30715/custom-images-as-screensaver-at-the-login-window-lab-environment for more info.

arpierson
New Contributor III

No, I'm afraid not. Also, since I've posted that, we ran into an issue with High Sierra, so it's not 100% usable. :(

jameson
Contributor II

I just tried the modified script and it works fine. The pictures are sliding quite fast - which parameter can you set time, so same picture stands there fx for 30 minutes or X minutes

arpierson
New Contributor III

That's the part that's messing up for us in High Sierra. There's a separate .plist file located at /System/Library/PrivateFrameworks/Slideshows.framework/Versions/A/Resources/Content/EffectDescriptions.plist that you can edit. You have to edit the key for JustASlide>mainDuration to the time you want, remove EffectDescriptions.plist from the target machine, and replace it with your edited EffectDescriptions.

For some reason on High Sierra (a reason I haven't had time to debug), it breaks the Classic screensaver altogether. Works well with at least Mojave, though.

jameson
Contributor II

Thanks for the input. Is there a easy way to edit this one - Can not get allowed saving or removing the old EffectDescripti on mojave it even when deploying with jamf

arpierson
New Contributor III

I copied the .plist to my desktop, edited the copy, added the edited copy to my .pkg that delivers the custom .plists, added rm /System/Library/PrivateFrameworks/Slideshows.framework/Versions/A/Resources/Content/Effect/EffectDescriptions.plist and then copied the new EffectDescriptions.plist. Here's the updated script (with some stuff that I'm trying to get High Sierra working):

macUUID=`ioreg -rd1 -c IOPlatformExpertDevice | grep -i "UUID" | cut -c27-62`
osMajor=$(sw_vers -productVersion | awk -F"." '{print $2}')
osMinor=$(sw_vers -productVersion | awk -F"." '{print $3}')

sleep 4

# Remove the current plist files
rm /Users/$3/Library/Preferences/ByHost/com.apple.screensaver.$macUUID.plist
rm /Users/$3/Library/Preferences/ByHost/com.apple.ScreenSaverPhotoChooser.$macUUID.plist
rm /Users/$3/Library/Preferences/ByHost/com.apple.ScreenSaver.iLifeSlideShows.$macUUID.plist
rm /System/Library/PrivateFrameworks/Slideshows.framework/Versions/A/Resources/Content/EffectDescriptions.plist

if [[ $osMajor -eq 14 ]] && [[ $osMinor -ge 2 ]]; then
    cp /private/var/screensaver/com.apple.screensaver.14.2.plist /Users/$3/Library/Preferences/ByHost/com.apple.screensaver.$macUUID.plist
    else
    cp /private/var/screensaver/com.apple.screensaver.14.1.plist /Users/$3/Library/Preferences/ByHost/com.apple.screensaver.$macUUID.plist
fi

cp /private/var/screensaver/com.apple.ScreenSaver.iLifeSlideShows.x.plist /Users/$3/Library/Preferences/ByHost/com.apple.ScreenSaver.iLifeSlideShows.$macUUID.plist
cp /private/var/screensaver/com.apple.ScreenSaverPhotoChooser.x.plist /Users/$3/Library/Preferences/ByHost/com.apple.ScreenSaverPhotoChooser.$macUUID.plist
cp /private/var/screensaver/EffectDescriptions.plist /System/Library/PrivateFrameworks/Slideshows.framework/Versions/A/Resources/Content/EffectDescriptions.plist

# Gives the logged on user access to the SlideShow folder & plist files
#chmod -R 755 /Library/Screen Savers/hcboe
chmod 755 /Users/$3/Library/Preferences/ByHost/com.apple.screensaver.$macUUID.plist
chmod 755 /Users/$3/Library/Preferences/ByHost/com.apple.ScreenSaverPhotoChooser.$macUUID.plist
chmod 755 /Users/$3/Library/Preferences/ByHost/com.apple.ScreenSaver.iLifeSlideShows.$macUUID.plist

killall cfprefsd

jameson
Contributor II

Seems the issue is SIP in Mojave, that I cannot get access to just overwrite this file. Bummer - not making it easy to modify the screensaver settings if they are stored inside system/library

There does not exist any options to do something in config profiles etc? or does there exist any third party software for screensavers ?
To enable sip on all computers that must be done through recovery mode, is to much work as we are talking "only" about screensaver

EUC600
New Contributor III

@jlang_remedy It seems after the 10.14.3 supplemental update (18D109) it no longer works again. Anyone know if these locations changed again?

/System/Library/Frameworks/ScreenSaver.framework/Resources/iLifeSlideshows.saver
/System/Library/Frameworks/ScreenSaver.framework/PlugIns/iLifeSlideshows.appex

cpresnall
Contributor

@DakotaS96 The iLifeSlideshows.saver appears to be gone after 10.14.3. the .appex file remains in the same location though.

sskamesh
New Contributor II

Yup. The screensaver doesn't work for me as well. I was using @jlang_remedy 's script. It's not working any more. Let me know if you guys find anything. We're testing Mojave atm. and I want it to be the latest for now whatever for our work. So, that when we deploy in future, people don't come ask for updating it.

Thanks!

Captainamerica
Contributor II

Those of you who have used Mojave and the script. Is it correct you then have disabled SIP to get this working ? (I know the script work now on latest mojave release)

billystanton29
New Contributor II

@jlang_remedy did you manage to resolve this on 10.14.3?

Seems like "Classic" isn't selected for us when we run the script.

Thank You!

sskamesh
New Contributor II

this is what we use now. Works on all version of macOS.

#!/bin/bash
# grab the system's uuid

if [[ `ioreg -rd1 -c IOPlatformExpertDevice | grep -i "UUID" | cut -c27-50` != "00000000-0000-1000-8000-" ]]; then
    macUUID=`ioreg -rd1 -c IOPlatformExpertDevice | grep -i "UUID" | cut -c27-62`
fi

export osMajor=$(sw_vers -productVersion | awk -F"." '{print $2}')
export osMinor=$(sw_vers -productVersion | awk -F"." '{print $3}')

if [[ $osMajor -eq 14 ]] && [[ $osMinor -ge 2 ]]; then
  defaults -currentHost write com.apple.screensaver CleanExit -string "YES"
  defaults -currentHost write com.apple.screensaver PrefsVersion -int 100
  defaults -currentHost write com.apple.screensaver idleTime -int 600
  defaults -currentHost write com.apple.screensaver moduleDict -dict moduleName -string "iLifeSlideshows" path -string "/System/Library/Frameworks/ScreenSaver.framework/PlugIns/iLifeSlideshows.appex" type -int 0
  defaults -currentHost write com.apple.ScreenSaverPhotoChooser identifier -string "/System/Library/Images"
  defaults -currentHost write com.apple.ScreenSaverPhotoChooser LastViewedPhotoPath -string "/System/Library/Images"
  defaults -currentHost write com.apple.ScreenSaverPhotoChooser SelectedFolderPath -string "/System/Library/Images"
  defaults -currentHost write com.apple.ScreenSaverPhotoChooser SelectedSource -int 4
  defaults -currentHost write com.apple.ScreenSaverPhotoChooser ShufflesPhotos -int 1
  defaults -currentHost write com.apple.ScreenSaver.iLifeSlideShows styleKey -string "ShiftingTiles"
else
  defaults write /Users/$USER/Library/Preferences/ByHost/com.apple.screensaver.$macUUID.plist CleanExit "YES"
  defaults write /Users/$USER/Library/Preferences/ByHost/com.apple.screensaver.$macUUID.plist PrefsVersion -int 100
  defaults write /Users/$USER/Library/Preferences/ByHost/com.apple.screensaver.$macUUID.plist idleTime -int 600
  defaults write /Users/$USER/Library/Preferences/ByHost/com.apple.screensaver.$macUUID.plist moduleDict -dict moduleName "iLifeSlideshows" path "/System/Library/Frameworks/ScreenSaver.framework/Resources/iLifeSlideshows.saver" type -int 0
  defaults write /Users/$USER/Library/Preferences/ByHost/com.apple.ScreenSaverPhotoChooser.$macUUID.plist identifier "/System/Library/Images"
  defaults write /Users/$USER/Library/Preferences/ByHost/com.apple.ScreenSaverPhotoChooser.$macUUID.plist LastViewedPhotoPath "/System/Library/Images"
  defaults write /Users/$USER/Library/Preferences/ByHost/com.apple.ScreenSaverPhotoChooser.$macUUID.plist SelectedFolderPath "/System/Library/Images"
  defaults write /Users/$USER/Library/Preferences/ByHost/com.apple.ScreenSaverPhotoChooser.$macUUID.plist SelectedSource -int 4
  defaults write /Users/$USER/Library/Preferences/ByHost/com.apple.ScreenSaverPhotoChooser.$macUUID.plist ShufflesPhotos -int 1
  defaults write /Users/$USER/Library/Preferences/ByHost/com.apple.ScreenSaver.iLifeSlideShows.$macUUID styleKey "ShiftingTiles"
  defaults write /Users/$USER/Library/Preferences/ByHost/com.apple.ScreenSaver.iLifeSlideShows styleKey "ShiftingTiles"
fi

defaults -currentHost write com.apple.screensaver askForPasswordDelay -int 0

cbruce
New Contributor III

Hi,
Great info here, but has anyone had to work with SaveHollywood utilizing a mp4 file? I am having 0 luck getting to work.

MTFIDjamf
Contributor II

@sskamesh For the top part of the script, relating to Mojave and above, do you run this once per Mac and it applies to all current and future users of the Mac, or do you have to run it once per user?