Many organisations like to set or pre-set the Desktop Picture of managed Macs. There are a few options for Mac Admins.
One of the commonly used methods may break in macOS Mojave because of the new security and privacy controls for AppleEvents, also known as TCC.
Getting the Image File to the Mac
Unless you want to use one of the default macOS Desktop Picture images, you will first need to get the image file on to the client. The best way of doing that is with an installer package.
Note: installing a single image file to
/Library/Desktop Pictures
is actually the first exercise/example in my book “Packaging for Apple Administrators.” Get that for a more detailed description.
I will use the same example desktop picture as in the book. You can use your own desktop picture or download BoringBlueDesktop.png
from the book’s resources.
Note: Desktop pictures on macOS can be many file formats. PNG and JPEG are most commonly used. The new dynamic desktop pictures of macOS Mojave have the
heic
file extension.
First create a project folder, with a payload
folder inside:
$ mkdir -p BoringDesktop/payload
$ cd BoringDesktop
Then copy the image to the payload
folder.
$ cp /path/to/BoringBlueDesktop.png payload
Then you can build a pkg with
$ pkgbuild --root payload --install-location "/Library/Desktop Pictures/" --identifier com.example.BoringDesktop --version 1 BoringDesktop.pkg
The resulting pkg file will install the image file in /Library/Desktop Picture
.
Note: the
pkgbuild
command has many options and arguments. If you get one of them slightly wrong it can lead to unexpected behavior or even break the installation. I recommend using a script to run thepkgbuild
command to avoid errors. You can find a sample build script here. Read the book for a more detailed explanation ofpkgbuild
and the build script. If you prefer, you can usemunkipkg
, which also simplifies and automates the process of building pkg installers.
This will provide the image in a location that the user might look for. However, for better management you want to set the desktop picture as well.
Lock Down the Desktop Picture
Once the image file is in place. You can set the desktop picture with a configuration profile. Many management systems will have an option in the ‘Restrictions’ payload where you can set the path to the desktop picture.
You can also use this custom profile:
You can learn all the ways to manage and install profiles in my other book ‘Property Lists, Preferences and Profiles for Apple Administrators’
With this configuration profile in place, the desktop picture is locked. The user can still open the Desktop preference pane but the selection will be ignored. You would need to be able to remove the profile to change the desktop picture again.
This is very useful in education and other strictly managed environments.
Suggesting a Desktop Picture
In other, less tightly managed environments, you might prefer to set an initial desktop picture, but allow the user to change it later.
The common means to do this has been to use an AppleScript command:
tell application "Finder" to set desktop picture to POSIX file "/Library/Desktop Pictures/BoringBlueDesktop.png"
If you want to run this from a shell script you would execute it with osascript
:
osascript -e 'tell application "Finder" to set desktop picture to POSIX file "/Library/Desktop Pictures/Sierra.jpg"'
Note that this sets a user preference so it should be run as the user. See this post for details.
However, with macOS Mojave, Apple is introducing new Privacy and Security measures which require user approval for processes to send AppleEvents. This will put a severe limit on the use of osascript
for admin scripts.
One solution would be to whitelist your management system’s agent which allows it to send Apple Events to the Finder. This requires managing the client with a user-approved MDM.
Another solution is to avoid AppleScript and Apple Events entirely.
Here comes the desktoppr
!
To do this, I wrote a simple command line tool which can read and set the desktop picture. Neil Martin had the brilliant idea to call it desktoppr
.
You can read the current desktop picture with:
$ desktoppr
/Library/Desktop Pictures/High Sierra.jpg
and set the desktop picture with
$ desktoppr "/Library/Desktop Pictures/BoringBlueDesktop.png"
When you have multiple displays, desktoppr
will list all desktop pictures:
$ desktoppr
/Library/Desktop Pictures/HotStepper.jpg
/Library/Desktop Pictures/LyricalGangster.jpg
/Library/Desktop Pictures/MrOfficer.jpg
When you pass a file desktoppr
will set it as the desktop picture for all screens:
$ desktoppr /Library/Desktop Pictures/NaahNananah.jpg
$ desktoppr
/Library/Desktop Pictures/NaahNananah.jpg
/Library/Desktop Pictures/NaahNananah.jpg
/Library/Desktop Pictures/NaahNananah.jpg
You can also set a specific desktop picture for a specific screen: (index starts at zero)
$ desktoppr 0 /Library/Desktop Pictures/HotStepper.jpg
$ desktoppr 1 /Library/Desktop Pictures/LyricalGangster.jpg
$ desktoppr 2 /Library/Desktop Pictures/MrOfficer.jpg
Managing with desktoppr
You can get the code for desktoppr
on Github and an installer package here. The installer pkg will install desktoppr
in /usr/local/bin
. When you want to run it from a management script it is safest to include the entire path:
/usr/local/bin/desktoppr "/Library/Desktop Pictures/BoringBlueDesktop.png"
Since the desktoppr
tool also sets user preferences, you still need to pay attention that it runs as the user.
For example, you could run desktoppr
from a LaunchAgent (deployed in /Library/LaunchAgents
so it affects all users:
This LaunchAgent will reset the Desktop Picture at every login.
If you want to set the Desktop Picture just once from a management or postinstall script (probably running as root) you can use the following to be safe:
When you find yourself building LaunchAgents or LaunchDaemons often (i.e. more than once) you should really consider using outset.
If you wanted to build an installer package that drops both the picture file and the LaunchAgent, you can do the following:
$ mkdir -p DesktopAndAgent/payload/
$ cd DesktopAndAgent
$ mkdir -p "payload/Library/Desktop Pictures/"
$ cp /path/to/BoringBlueDesktop.png "payload/Library/Desktop Pictures/"
$ mkdir -p payload/Library/LaunchAgents/
$ cp /path/to/com.scriptingosx.setdesktop.plist payload/Library/LaunchAgents
$ pkgbuild --root payload --install-location / --version 1 --identifier com.scriptingosx.desktopandagent DesktopAndAgent-1.pkg
See also https://gist.github.com/gregneagle/6957826 and https://grahamgilbert.com/blog/2013/10/28/setting-a-desktop-picture-in-mavericks/ for examples of using Python and pyobjc and the NSWorkspace APIs to do similar things.
Not as cool as Swift, but then you don’t need to install a 6.5MB tool just to set a desktop picture 🙂
Now only if there was as simple a tool for setting the profile pic!
https://scriptingosx.com/2018/10/changing-a-users-login-picture/
Very useful profile share – thank you!
In general, how are these profiles generated?
Is there a common library/templates of what attributes of the system can be affected?
Thanks again for sharing,
-Gary
Gary,
Apple documents how to build configuration profiles and many payloads here: https://developer.apple.com/enterprise/documentation/Configuration-Profile-Reference.pdf
Most MDM Solutions provide means to build configuration profiles and you can use those as a template. You can also learn more about profiles in my book https://geo.itunes.apple.com/book/property-lists-preferences-profiles-for-apple-administrators/id1213903756?mt=11&at=1001lpyX
Hi Ab,
Thank you for great write-up, definitely getting your book.
Quick question on the same topic of background images – is it possible to construct a profile to enforce just the lock screen background image, independent of the desktop background?
Not trivially. Especially since the way the login window background window is generated changed between macOS version and if you have FileVault enabled the ‘Login window’ is actually a Firmware process. I consider trying to change the system behavior here not worth the effort.
You can add custom text to the login window with a configuration profile or defaults command, you can add a EULA or info pane with a Policy Banner https://support.apple.com/en-us/HT202277
If you want to gain complete control of the login UI and workflow, I would recommend taking a look at Nomad-Login: https://gitlab.com/orchardandgrove-oss/NoMADLogin-AD
Nice.
Is there a way to modify the placement (Fill screen, fit to screen, stretch to fill screen, centre, tile)? ’cause that would be awesome.
not yet…
https://github.com/scriptingosx/desktoppr/issues/3
what is the team identifier and bundle ID to use for MDM deployment of the desktoppr app in Catalina? It’s blocked by “security & privacy” requiring the user to click an “allow” button when it’s first installed.
Thanks!
Thanks for pointing that out! I have just built and published a notarized installer for
desktoppr
: https://github.com/scriptingosx/desktoppr/releases/tag/v0.2I am curious, though. What is your workflow, that users are installing desktoppr manually?
Just installed desktoppr on my machine (OS 10.15.1), when I run the $ desktoppr command to find the current path of my desktop pictures, I get the message
-bash: $: command not found
Anything I need to do additionally for this to work? Been looking for a solution like this for a long time! Thanks!
You are probably trying to run the toll in a context where the PATH is not set up in the expected way. Try using the full path to launch the tool: /usr/local/bin/desktoppr