Wallpaper in a Encrypted Volume
The Problem
I have three volumes in my Mac. I decided to encrypt the two non-boot volumes just for the sake of it. So I did that.
The next time I booted into the OS, I was greeted by an ultra-friendly dialog box asking for passwords. I did not want to do that every time I restart, so I let it remember the passwords in keychain. And the next time I restarted, I found my fine wallpaper was replaced by the default galaxy-in-space image, which I did not really fancy.
Solution Number One
I knew the reason was that the encrypted volumes were mounted after the desktop was loaded. And given the stuborn-ness of Mac OS, it is probably humanly impossible to change that order. So I looked for an alternative — writing a script to kill the Dock application, which automatically reloads the desktop, and somehow running this script when I log in. If I am lucky enough, the script might be run after the encrypted volume is mounted. Here is the script,
:::Bash
#!/bin/sh
exec killall Dock
I ran it to confirm its correctness. Then I added it to my “Login Items” (try a better name next time, Apple). But, it did not work. Apparently it was executed before the volume was mounted.
Solution Number Two
I had to search on the web to start my second attempt. This time it
was a more apple-ish method. One can attach a script to a directory
in Mac by setup a “folder action”, so that when there are some changes
to that directory, the script gets to run. So in principle I could do
this to /Volumes
, and when a volume is mounted, the folder action
should be done automatically. The problem is I do not like my desktop
to flick all the time, so I need to know the mounted volume has a
specific name. Noticing “Shared” being the name, I wrote an
applescript for that,
:::Applescript
on adding folder items to this_folder after receiving MountedVolumes
repeat with Volume in MountedVolumes
if name of Volume is "Shared" then
quit application "Dock"
end if
end repeat
end adding folder items to
I did not know if this is correct. I did not even read it a second time, and I suggest you avoid doing that as well. Applescripts are so purely ugly, one would have nightmares after reading too many of them. If one insists on getting some nightmares, I recommend Peskin — at least it has much more contents.
So I attached the script to /Volumes
, and tried to unmount and mount
the encrypted volume. Nothing happened (well, I mean besides the volume
being unmounted and mounted...). Awesome. I did not like this method
in the first place.
Solution Number Three
So I did more search on the web, and found that the daemon launcher in
Mac was launchd
. It has a bunch of interfaces. One may use
launchctl
to start or stop a daemon, to list all daemons alive, to
list all daemons available, and much more. Daemons are defined with
XML files. A feature particularly useful in my scenario is the
ability to run a daemon when a volume is mounted. So I created the
following launchd
job, and saved it as a plist under
~/Library/LaunchAgents
,
:::XML
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC -//Apple Computer//DTD PLIST 1.0//EN
http://www.apple.com/DTDs/PropertyList-1.0.dtd >
<plist version="1.0">
<dict>
<key>Label</key>
<string>org.darksair.refreshdesktop</string>
<key>ProgramArguments</key>
<array>
<string>/Users/corsair/programs/refresh-desktop.sh</string>
</array>
<key>KeepAlive</key>
<false/>
<key>StartOnMount</key>
<true/>
<key>LaunchOnlyOnce</key>
<true/>
</dict>
</plist>
And refresh-desktop.sh
ran like thus
:::Bash
#!/bin/sh
FileVolList=/tmp/volume-list.txt
if [ ! -e ${FileVolList} ]; then
touch ${FileVolList}
fi
if ! grep '^Shared' ${FileVolList} > /dev/null; then
ls -1 /Volumes > ${FileVolList}
if grep '^Shared' ${FileVolList} > /dev/null; then
# Shared is mounted.
exec killall Dock
fi
fi
ls -1 /Volumes > ${FileVolList}
Then I restarted the machine, and found that several seconds after the encrypted volume was mounted, the desktop flickered, and the correct wallpaper was loaded. Another stupid problem solved!