Wednesday, March 13, 2013

OS X Mountain Lion Screensaver at the Loginwindow


With the release of OS X Mountain Lion (10.8), Apple discontinued supporting custom slidesavers over the loginwindow. Prevously, on OS X Lion, we used an existing slidesaver and modified it to fit our needs as document here: http://www.mactech.com/articles/mactech/Vol.26/26.02/2602MacEnterprise-CustomSlideShowScreenSavers/index.html

Moving ahead with Mountain Lion requires that we take another look at how we configure the loginwindow screensaver. If you're not interested in doing things using the Apple way, you may like the prepackaged solution provided by University of Utah called "10.5 Logout Saver Screen Preserver": http://www.macos.utah.edu/documentation/system_deployment/xhooks.html

If you're still interested a way to use a folder of images as a screensaver for OS X Mountain Lion and you don't want to install extra XHooks stuff, keep reading...

The basic crux of the issue is that there is no GUI for configuring the loginwindow screensaver to use a folder of images. In fact, there isn't any documentation from Apple, that I can find, to configure the loginwindow screensaver. To configure the screensaver we'll have to use the System Preferences GUI and the terminal, so lets get started!

The first step involves configuring the screensaver inside a user account. This is the simplest of the steps and as such I won't go into much detail. You open the Screen Saver preference pane and select a folder of images to use. That's it, just remember to set the users screensaver back to whatever you would like it to be when you're done.

Now that you've selected the folder, two new files have been created for your user. These two files, named com.apple.ScreenSaverPhotoChooser.GUID.plist & com.apple.ScreenSaver.iLifeSlideShows.GUID.plist (Where GUID is your machines ByHost identifier), hold settings that configure the "iLifeSlideshows.saver". The "iLifeSlideshows.saver" ends up being the replacement to your custom slidesaver from the previous OS. Instead of the system using your slidesaver, it uses the iLifeSlideshows.saver and looks for the aforementioned preference files to determine which folder of images should be shown. The System Preferences writes these preference files to /Users/username/Library/Preferences/ByHost/. Find them and copy them to /Library/Preferences now, I'll wait here.

So, now that we've got those two files moved to /Library/Preferences, you should rename them to remove the ByHost GUID. You will end up with file names /Library/Preferences/com.apple.ScreenSaver.iLifeSlideShows.plist & /Library/Preferences/com.apple.ScreenSaverPhotoChooser.plist. Lets take a look at these and modify them to our needs. 

To view the files we can use the defaults command. In the Terminal.app type this:
defaults read /Library/Preferences/com.apple.ScreenSaverPhotoChooser.plist
defaults read /Library/Preferences/com.apple.ScreenSaver.iLifeSlideShows.plist 
 Our first file "com.apple.ScreenSaverPhotoChooser.plist" shows this:

{
    CustomFolderDict =     {
        identifier = "/Library/Preferences/Slides/edu.psu.slides";
        name = "edu.psu.slides";
    };
    LastViewedPhotoPath = "";
    SelectedFolderPath = "/Library/Preferences/Slides/edu.psu.slides";
    SelectedSource = 4;
    ShufflesPhotos = 1;
}
We can see that the preference file has the directory of images that we set in System Preferences. We can also see a few other keys are set. If you want to change the path to the slides, you could do so by editing the SelectedFolderPath and identifier under the CustomFolderDict. Hopefully we've got those set correctly and can move on. In my testing, I found that the SelectedSource key and CustomFolderDict were unnecessary. LastViewedPhotoPath is auto generated, so really the only keys needed are SelectedFolderPath and ShufflesPhotos. Your milage may vary.


The second file "com.apple.ScreenSaver.iLifeSlideShows.plist" shows this:
{
    spansScreensKey = 0;
    styleKey = Classic;
}
The spansScreensKey, I assume, tells the screensaver to show on multiple screens. I've not yet tested this. The styleKey seems to be the way in which the photos appear. One of the alternate styleKeys is "Flipup". I'd like to collect more here, eventually.

Now that we've modified the two files from our user account, we need to tell the system to use the iLifeSlideshows.saver at the loginwindow, as well as how long to wait before doing so.
Check to see if you've already got a "com.apple.screensaver.plist" with this command:
defaults read /Library/Preferences/com.apple.screensaver.plist
Chances are you've not got one. That's fine, we can make one very easily. To configure the system to use the "iLifeSlideshows.saver", which will show our folder of images, we can use this defaults command:
defaults write /Library/Preferences/com.apple.screensaver.plist loginWindowModulePath "/System/Library/Frameworks/ScreenSaver.framework/Resources/iLifeSlideshows.saver"
Careful of line breaks when copying and pasting, check before you hit enter!

Once we've got the correct screensaver chosen, we need to tell the system how long to wait before activating the screensaver over an idle logininwindow. Use this command with the number of seconds to wait:
defaults write /Library/Preferences/com.apple.screensaver.plist loginWindowIdleTime 60
Hopefully it makes sense to you that this would set the loginwindow to show the screensaver after 1 minute. 

Now you can restart your machine and your folder of pictures should appear over the loginwindow after a minute of being idle! Try packaging the files and picture folder for making the deployment easier in the future.

TL;DR

Enable screensaver with these three preference files and a folder of images at /Library/Preferences/imagefolder/:

File: /Library/Preferences/com.apple.screensaver.plist
Contents:
{
    loginWindowIdleTime = 4;
    loginWindowModulePath = "/System/Library/Frameworks/ScreenSaver.framework/Resources/iLifeSlideshows.saver";
}

File: /Library/Preferences/com.apple.ScreenSaverPhotoChooser.plist
Contents:
{
    SelectedFolderPath = "/Library/Preferences/imagefolder";
    ShufflesPhotos = 1;
}

File: /Library/Preferences/com.apple.ScreenSaver.iLifeSlideShows.plist
Contents:
{
    spansScreensKey = 0;
    styleKey = Flipup;
}

NOTES:

Different StyleKeys:
  • Classic - Images appear centered
  • Flipup - Images flip into place in front of previous pictures

Tuesday, February 19, 2013

VMWare Fusion and system_profiler fail

One of the newest additions to my toolset is VMWare Fusion 5. While I've attempted to use VMs in the past for development and testing, I've never really liked the environment. It always seemed slow and difficult to manage when I attempted to bend it to my needs. Luckily, I've had plenty of spare Macs to test on when needed.

I decided to give the tool another shot, as I really think the rollback feature would be helpful when testing software packages. It certainly seems quicker to revert to a snapshot instead of re-installing the OS every time I need to test an installer.

I started my test of VMWare Fusion 5 by booting from a USB drive to restore an OS disk image. I followed this article from VMWare on booting from an external USB drive. Once completed, the machine rebooted as I expected. However, what I didn't expect was the failure of my first boot script to correctly install a few packages.

Looking closer at the logs, I noticed that my script used this line to set the internal drive variable "HD_Path", which is used to tell the installer command the path to install the packages to:
HD_Path=`system_profiler SPSerialATADataType|awk -F': ' '/Mount Point/ { print $2}'|head -n1`
(Side Note: The above command has always worked to get the internal disk of a Mac, even when multiple internal and external disks were present OR even if booted from a the network!)

Running the system_profiler command in the terminal of the virtual machine showed me why it failed. Because "system_profiler SPSerialATADataType" returns blank for virtual machines! I found a bug posted here from 2008 that discusses the problem, but does not provide a solution.

So, I may still try to find a place that using VMWare works for me, this doesn't seem to be it. I am not currently wanting to re-writing scripts just to take advantage of snapshots, although I may find it necessary eventually.

If you're in this spot, try using tools like 'diskutil list' and 'df' to get the disk lists.

Friday, January 18, 2013

Idle Logouts in Mac Labs


I've been playing with Real Studio recently and have been enjoying my learning experience. Justin Elliott has been giving me some extra help when I get stuck and we ended working on an app together for our labs.

Problem:
Users sometimes forget to log out, this can be a security risk. Using AppleScripts or safe commands to log users out doesn't always work as expected, think open Microsoft Word doc with changes. In order to force users to log out, we needed to develop an application to do so.

Solution:
The PSU Idle Logout.app was written in Real Studio to force machines to reboot when users hit a specified idle time. The time is specified in a plist and compared to the amount of time the USB HID devices (mouse and keyboard) have been idle. Here is the line of code used to get that time:
echo $((`ioreg -c IOHIDSystem | sed -e '/HIDIdleTime/ !{ d' -e 't' -e '}' -e 's/.* = //g' -e 'q'` / 1000000000))
If time reaches what has been specified as the idle limit, the computer will reboot by running a script. This solution requires that the /etc/sudoers file is modified so that standard users can reboot the machine with the script. See the GitHub repository for more information!

The Real Studio code and application are available on GitHub for modification and use. Please let me know if it helps you!

Update:
The repository has been moved into the CLC Mac Team organization in GitHub. Please use this link:
https://github.com/CLCMacTeam/IdleLogout

Friday, June 15, 2012

Editing the Apple Menu

¡Super-Awesome Edit!


Don't you just love it when your super long work around to disable shutting down can actually be accomplished with two simple commands? I do!


sudo defaults write /Library/Preferences/com.apple.loginwindow ShutDownDisabled -bool true
sudo defaults write /Library/Preferences/com.apple.loginwindow ShutDownDisabledWhileLoggedIn -bool true


These two commands will disable the Shut Down option at the Login Window and the pop up that is shown with a click of the power button or the control-eject shortcut. I'm unable to reproduce, but I've been told it remove the Shut Down option from the Apple menu and if a user does use the forced shut down shortcut (control-option-command-eject), the computer simply reboots.

Source:
http://hints.macworld.com/article.php?story=20091104040449752

Original Post:

One of the more exciting things about upgrading Mac Mini's in classrooms is that they can be hidden! Now that the Mini's Superdrive has been moved to an external device, the Mac can be neatly hidden away and attached to a USB hub for peripherals. Now that the Mini is hidden, we have a new concern. What if it gets turned off?

With the meat of the Mac hidden, we had concerns about users accidentally shutting it down. There would little to no way for them to reach a power button. I've seen other companies solder wires to the power switch to allow an external button, but have you seen the new Mini's guts? Our solution was to remove the Shut Down and Sleep options.

After some research, this seemed like a simple fix. To remove the Shut Down and Sleep options from the Apple Menu, all I had to do was edit a NIB file, remove an object, save and reboot. However, this simple trick also had a negative side effect. The Finder would crash, repeatedly, when I selected the Apple Menu.

Thanks to StackTrace for the initial answer:
http://apple.stackexchange.com/questions/22535/can-i-remove-the-log-out-item-from-the-apple-menu/53810#53810

Here is the file I needed to edit
/System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/HIToolbox.framework/Versions/A/Resources/English.lproj/StandardMenus.nib/objects.xib

After messing around a bit, I started looking closely at the objects. Each object had it's own "id". When I was looking for the Shut Down option in the Carbon.framework, I remembered seeing lists of ids in other interface files. I started to wonder if these id's were referenced else where, causing the Finder to unexpectedly quit when they couldn't be found.


Example Object:
<object class="IBCarbonMenuItem" id="238">
  <string name="title">Shut Down…</string>
  <boolean name="dynamic">TRUE</boolean>
  <boolean name="notPreviousAlternate">TRUE</boolean>
  <ostype name="command">rsdn</ostype>
</object>

I found, in the same objects.xib file, all of the id's under reference tags. After I removed all of these references, the Finder behaved and the Shut Down and Sleep options were gone!

References:

<reference idRef="236"/>
<reference idRef="285"/>
<reference idRef="238"/>


If you decide to remove the Sleep and Shut Down options, look for these id's in object and reference tags. Delete the entire object, one for the Sleep option and two for the Shut Down option, and each of the references.

id's:
Sleep - 236
Shut Down - 238, 285

As an aside, there are two Shut Down options because one is for the standard Shut Down (graceful shutdown) and the other for holding the option key and clicking Shut Down (force a shut down). 

P.S. I can't tell you how hard it was for me not to type Shit Down...