jump to navigation

Wireless Installer – The Next Generation August 27, 2009

Posted by bigmaconcampus in Mac Tech.
Tags: , , , , , , , , , , , , , , , , , , , , ,
25 comments

Ok, after originally posting the code for my wireless installer, I’ve updated the code earlier in the summer and keep promising to post an update. Without further adieu, here it finally is.

*NOTE* 9/29/09
There were some errors in the applescript sections of the original post. These should be correct now. Oops.

*NOTE* 12/21/09
Gave up fighting wordpress to display the code correctly so that it would compile correctly if someone copy/pasted it. Now have a direct link to download the working files at the bottom of this post. Sorry for the delay/problems.

Intro
Since I couldn’t remember specifically what I changed (several bug fixes, some major, some minor), I’ll re-post the entire thing here. It has been tested on over 1700 Macs since the beginning of June 2009, so I consider it fairly solid at this point.

There was an entire section redone in C code since there were certain APIs that could only be addressed that way. This was also the ONLY piece that was a reminant of a GUI based version I’d made a year beforehand. Now, all command line, YEAH. (Thanks Kim!) Also, now moves the newly added wireless network to the top of the preferred list so connection time is quicker (noticed that with users that had 20+ wireless networks, adding it to the end of the list resulted in several minute long connection times).

The only issues I’ve run into is that on occasional runs, the installer will not pickup the wireless username correctly (the main script thinks that the wireless username is blank). I haven’t been able to narrow down what causes it directly (I think it has to do with running the installer partially and quitting at a certain spot, which must be leaving some clutter behind, but haven’t directly proved this yet), but have added code to recognize the problem and exit with an error. Most times, running the installer a second time will work fine. (If anyone happens to figure it out, please let me know in the comments)

The other small issue shows about one in a hundred runs and I consider it an applescript bug. Sometimes the portion that is applescript won’t allow the user to type in the dialog box. A reboot solves this behavior.

This installer basically works the same as before, it is crammed into a PackageMaker .pkg file and runs as a postscript to perfom the setup. The beauty of this is that it can be posted on a website for the user’s to run themselves and doesn’t require a tech to setup their wireless for them. (Makes our lines MUCH shorter). If you are confused by any of the details, refer to the previous post for a deeper description of some portions.

It’s in several scripts in several different languages (Four in all I think, we almost had some perl in it, but I’m a Bash junkie and got it to work in less lines in Bash :P )

Change Log

July 2009
Version 3.6
Fixed bug that caused a blank wireless username in certain situations
Fixed bug with a ‘space’ in the Mac password
Wireless network is now added in the top location of preferred networks to enable faster connection
Added more error codes
Added better error descriptions
Added ‘retry counter’ to dialogs
Lowered number of retries from five to three

April 2009
Version 3.5
Rebuilt Keychain creation mechanism in C to solve several bugs centering around creation of ACL of Keychain and Assistive Devices settings.
Added Mac OS X 10.6 enhancements
Increased speed of installer
Added second wireless password test in case of system outage

March 2009
Version 3.1
Made compatible with Mac OS X 10.6 (Snow Leopard)
Added several exceptions for MacBook Air hardware types due to lack of ethernet port
Streamlined method of fixing certain symbol characters in passwords
Fixed bug with toggling Assistive Devices settings
Modified handling of certain preference files and previous Enterprise level network setups
Added steps to handle a blank Mac Password
Added error code for a corrupt login.keychain that cannot be unlocked

Final Important Info
After wrestling with WordPress attempting to get the code posted correctly, I’ve given up and decided to instead post a link to download the working files so that anyone interested can just download the pieces and package it themselves.

There are three applescripts, used to obtain and test usernames and passwords, and cleanup Keychain Items, that are called by the Main Script. These feed back the variables for username and password to the parent script.

The Mac password cannot be blank (I wouldn’t recommend a user have a blank password anyway) nor can it contain a space (causes problems with the script).

Some items in remove_keychain_items.scpt need to be edited manually (Names of keychain items). Also, if the keychain is locked with a different password than the main user account password, the script will error at this step.

C Programming Section:
This section replaced the part that would actually set the access level for the wireless to get to the keychain item. Before it used GUI Applescript and relied on Assistive Devices to be able to click a single ‘OK’ button. Using C to create the keychain item and set the ACL to allow the eapolclient to access the keychain fixes the issues with doing it the previous way.

This C code should be compiled for both Intel and PowerPC separately and the resulting files should be named:
AddKeychainItem_Intel
AddKeychainItem_PowerPC

The parent script determines the processor type and will run the appropriate version of the executable.

You would need to do a find/replace in this section of code for wirelessnetworkname and put in the name of your particular wireless network.

Download working files
Wireless Installer

Hopefully the new and improved version (which is still not 100% complete, but getting closer) will help someone out there. If so, drop a comment.

Advertisements

But who would be the Best Man? August 25, 2009

Posted by bigmaconcampus in Rhinoism.
Tags: , , , ,
1 comment so far

While making lasagna with Rhino one evening, I let her take a nip at the mozzarella and she commented:

“Mmmmmm, I’m going to have to marry that cheese some day.”

Windows OS installer for Mac August 20, 2009

Posted by bigmaconcampus in Mac Tech.
Tags: , , , , , , , , , , , , , , , , , , ,
add a comment

As part of a group of installers I’ve developed for our University, the one that I thought would be the most difficult, but turned out to be the easiest was the one that will install a Windows OS as a dual-boot on the Mac.

This is not necessarily a fully automated method (like I would use in a lab situation), but rather an easy to use installer that can be posted on a intranet website for student (primarily students), faculty, employee use. It allows us to put Windows on Macs that are not our property and therefore we don’t have admin rights on the machine.

This is a flat-package (.pkg) that contains the necessary scripts to download a Windows image (created with Winclone) via curl, partitions the hard drive (35 GB partition) and then clones the downloaded image onto the second partition that was just created. All the user does is click a few buttons and the installation is fully automated. The installer package is relatively small at around 1 MB. The heavy lifting is done by the script downloading the image file to a /tmp location during the installation.

With the second version, an overlay window was added (using iHook) that allows a progress bar to give the user some feedback as to the status of the installation. We found some people were getting impatient and shutting off their computers thinking that the installation had frozen (Total time for this part was about 20-30 minutes), which was necessitating the need for better user feedback.

Also found that the image for Windows Vista needed to be sysprepped to function with all the varying Apple hardware. Unfortunately, this doubles the installer time. Sysprep takes about 20-30 minutes to do it’s thing. And reboots several times as well. But it is worth it to have a single image work on the varying Apple hardware. The image also had to move through the various hardwares starting from oldest to newest to load all of the bootcamp drivers. Doing it in a different order tended to kill Vista. Hopefully things will be smoother with Windows 7.

We have plans to make the third version use a bit torrent to download the image rather than curling the file from a single webserver. The beating the server takes during student setup workshops is heavy (20-50 user’s all trying to download the same 6.5 GB file at the same time). Switching to a torrent based download should relieve the server strain and speed up the download time for the clients when a large number run it simultaneously.

Here are the main scripts that performs all the tasks. It is kicked off as a postscript from a Packagemaker flat-package that is downloaded from a internal website (on purpose to keep the rest of the world from being able to access it). The package includes the Winclone command-line pieces necessary for cloning, but not the actual image file. That is downloaded separately by the script. iHook is also included in the package for the feedback.

Postscript for Package

#!/bin/sh
PATH=/bin:/usr/bin:/sbin:/usr/sbin export PATH

### This postinstall script will kick start the actual Vista
### Installer script and Feedback window to show progress

/private/tmp/foo/iHook/iHook.app/Contents/MacOS/iHook --no-titlebar --script=/private/tmp/foo/windowsvista/vista_installer.sh

ERROR=`grep ERROR /Library/Logs/Vista_Installer_For_Mac.log | cut -c 1-6`
if [ "$ERROR" != "" ]; then
rm -rf /tmp/clemson
$ERROR
fi

exit 0

The first line engages the main script. The ERROR section is just a test for any errors that might have occurred so that the installer will error properly if there was an error deeper in the other script. Found it was the easiest way to communicate between the installer app, iHook, and the nested scripts. The installer has a tendency to exit successful even when an error occurs if this part is left out.

Main Script referred to in the previous postscript that is run by iHook (vista_installer.sh):

#!/bin/sh
PATH=/bin:/usr/bin:/sbin:/usr/sbin export PATH

### Script created by Bryan Lee,
### April 2008.
### Modified November 2008 for new Apple hardware and
### to add the feedback mechanism.
###
### This postinstall script downloads the Windows image files
### in the proper temp directory and sets the correct permissions.
### Then partition the hard drive into 2 partitions. Finally, clone
### the Windows image onto the 2nd partition.
###
### iHook is used to give feedback to the user during the process.
###
### Requires iHook be installed in the /tmp directory
### Requires Winclone.perl be modified to redirect stderr to
### PROGRESS_FILE path during the restore process
### like the following example:
###
### do_command("=====restoring image======","/usr/bin/gunzip -c \
### "${image_dir}/boot.img.gz\"| \"$ntfstools_dir/ntfsclone\"
### --restore-image --overwrite \"$ntfs_partition\" - 2>&1 >
### /private/tmp/foo/windowsvista/winclone_progress.txt");
###
### Depends on Package installer to download Windows image file
### to /tmp directory
###

# Setup Location of Log file
LOG="/Library/Logs/Vista_Installer_For_Mac.log"

# Setup initial state for iHook Window
echo "%LOG OPEN" $LOG
chmod a+r $LOG
echo "%BECOMEKEY"
# echo "%TITLE Windows Vista Installer for Macintosh"
echo "%WINDOWLEVEL HIGH"
echo "%WINDOWSIZE 800 600"
echo "%WINDOWPOSITION CENTER"
echo "%WINDOWZOOM ENABLE"
echo "%HIDETIMER"
echo "%BACKGROUND /private/tmp/foo/iHook/windowsvistaformac_background.jpg"
echo "%BACKGROUNDSCALING TOFIT"

### Cleanup any possible files leftover from a previous run of the installer
### that would cause issues if present
rm -rf /private/tmp/foo/windowsvista/boot.img.gz
rm -rf /private/tmp/foo/windowsvista/winclone_progress.txt

### Set initial blank variables
PROGRESS=""
IHOOK_PERCENT=""
DOWNLOAD_PERCENT=""
PREVIOUS_FILE_SIZE=""
CURRENT_FILE_SIZE=""
KILL_CURL=""
SECOND_PARTITION_NAME=""

#####################
### FUNCTIONS ###
#####################

# Function for making computer beep three times
BEEP_THREE_TIMES ()
{
LIMIT=3 # Upper limit
a=0
while [ $a -le "$LIMIT" ]; do
a=$(($a+1))
echo "%BEEP"
sleep .5
done
}

### Set PID of iHook (to kill) in case of error
KILL_IHOOK=`ps acx | grep iHook | cut -c 1-5`

### Must set the size of this variable to the size of the image file in Kilobytes
### Using the following command on the image directory
### ls -sk | grep total | cut -c 7-15
### Current values for Vers2 is 6734820. Round down to the nearest MB
TOTAL_SIZE="6734000"

### Must set the path to the file that contains the progress from Winclone
PROGRESS_FILE="/private/tmp/foo/windowsvista/winclone_progress.txt"

#####################
### Initial tests ###
#####################

### Test for Processor type ###
HARDWARETYPE=`system_profiler -detailLevel mini | grep "Processor Name" | awk '{ print $3 }' `
if [ "$HARDWARETYPE" != "Intel" ]; then
BEEP_THREE_TIMES
echo "%WINDOWLEVEL NORMAL"
echo "exit 9, ERROR: Computer Hardware Cannot support Windows"
osascript -e "tell application \"iHook\" to activate"
osascript -e "tell application \"iHook\" to display dialog \"This computer does not support running Windows because is does not have an Intel Processor.\" & return & return & \"This installation will now exit with an error.\" buttons {\"OK\"} default button 1 with icon caution with title \"Windows Vista Installer for Mac\""
osascript -e "tell application \"Installer\" to activate"
kill $KILL_IHOOK
exit 9
fi

# Check to see if a second partition already exists, or some other odd situation
SECOND_PARTITION_NAME=`df | grep /dev/disk0s3`
if [ "$SECOND_PARTITION_NAME" != "" ]; then
BEEP_THREE_TIMES
echo "%WINDOWLEVEL NORMAL"
echo "exit 8, ERROR: Multiple Partitions Exist"
osascript -e "tell application \"iHook\" to activate"
osascript -e "tell application \"iHook\" to display dialog \"Multiple Partitions Already Exist\" & return & \"This installer can not be run on this system without removing the secondary partition\" & return & return & \"Please contact Jenny at 867-5309.\" & return & return & \"This installation will now exit with an error.\" buttons {\"OK\"} default button 1 with icon caution with title \"Windows Vista Installer for Mac\""
osascript -e "tell application \"Installer\" to activate"
kill $KILL_IHOOK
exit 8
fi

### DOWNLOAD STAGE 1 ###

# Start Progress Bar for Downloading Image
echo "%BEGINPOLE"
echo "Downloading Windows Image"

### Change directory to the Windows temp directory created by the installer
### and set the current file size variable

cd /private/tmp/foo/windowsvista/
CURRENT_FILE_SIZE=$(ls -sk | grep total | cut -c 7-15)

### Download image needed for Windows imaging from the Web server
echo "Starting Download of Windows image"
curl -O http://www.foo.edu/windows/vista/version2/boot.img.gz &

### Loop to update download progress constantly until complete
until [ "$CURRENT_FILE_SIZE" -ge "$TOTAL_SIZE" ]; do
sleep 7
DOWNLOAD_PERCENT=`echo "($CURRENT_FILE_SIZE * 100) / $TOTAL_SIZE" | bc`
echo "%$DOWNLOAD_PERCENT"
echo "Download Is $DOWNLOAD_PERCENT Percent Complete"
CURRENT_FILE_SIZE=$(ls -sk | grep total | cut -c 7-15)
if [ "$PREVIOUS_FILE_SIZE" = "$CURRENT_FILE_SIZE" ]; then
BEEP_THREE_TIMES
echo "%ENDPOLE"
echo "%WINDOWLEVEL NORMAL"
echo "exit 1, ERROR: Image file did not download successfully"
osascript -e "tell application \"iHook\" to activate"
osascript -e "tell application \"iHook\" to display dialog \"An error has occurred while attempting to download the Windows Image File.\" & return & return & \"Please verifiy your network connection and try the installation again.\" & return & return & \"This installation will now exit with an error.\" buttons {\"OK\"} default button 1 with icon caution with title \"Windows Vista Installer for Mac\""
osascript -e "tell application \"Installer\" to activate"
KILL_CURL=`ps acx | grep curl | cut -c 1-5`
kill $KILL_CURL
kill $KILL_IHOOK
exit 1
fi
PREVIOUS_FILE_SIZE=$CURRENT_FILE_SIZE
done

echo "%100"
echo "Download Is 100 Percent Finished"
sleep 2

echo "%ENDPOLE"

### Set correct permissions on script files

chmod u+rwx /private/tmp/foo/windowsvista/winclone.perl
chmod u+rwx /private/tmp/foo/windowsvista/gptrefresh
chmod u+rwx /private/tmp/foo/windowsvista/ntfsclone
chmod u+rwx /private/tmp/foo/windowsvista/ntfscp
chmod u+rwx /private/tmp/foo/windowsvista/ntfsresize
chmod u+rwx /private/tmp/foo/windowsvista/size
chmod u+rwx /private/tmp/foo/windowsvista/BCD
chmod u+rwx /private/tmp/foo/windowsvista/boot.mbr
chmod u+rwx /private/tmp/foo/windowsvista/partitionid
chmod u+rwx /private/tmp/foo/windowsvista/description
chmod u+rwx /private/tmp/foo/windowsvista/vista_installer.sh

### PARITIONING STAGE 2 ###

### Properties ###
#
# These items must be modified to suit your environment before
# implementing this script! You do not need to make any other
# modifications to this file than these properties.
# Note: the target disk is determined programatically by finding
# the internal drive that is already partitioned using the GPTFormat
# If you have multiple drives (physical drives, not partitions)
# attached to your client machines that are partitioned using the
# GPTFormat, you will need to specify the target disk manually.

echo "Partitioning Drive. Please be patient."
sleep 2

# Partition the internal disk that is already using the GPT partitioning scheme
tdisk=`diskutil list | awk '/GUID_partition_scheme/ {print $NF}'`
totalSize=`df -m | awk "/$tdisk/"' {total+=$2} END {print total}'`
macSize=$(($totalSize - 35000))
diskutil resizeVolume /dev/$tdisk"s2" ${macSize}M MS-DOS WINDOWS 0b

### Check to see if 2nd parition was created
SECOND_PARTITION_NAME=`df | grep /dev/disk0s3 | grep "WINDOWS"`

if [ "$SECOND_PARTITION_NAME" = "" ]; then
BEEP_THREE_TIMES
echo "%WINDOWLEVEL NORMAL"
echo "exit 2, ERROR: Paritioning failed"
osascript -e "tell application \"iHook\" to activate"
osascript -e "tell application \"iHook\" to display dialog \"Partitioning was not successful! \" & return & return & \"Possible causes include: \" & return & \"More than one partition already exists\" & return & \"An external hard drive is connected\" & return & \"A rare issue with the Partition Map of the hard drive\" & return & return & \"Please try installation again or contact Jenny at 867-5309.\" & return & return & \"This installation will now exit with an error.\" buttons {\"OK\"} default button 1 with icon caution with title \"Windows Vista Installer for Mac\""
osascript -e "tell application \"Installer\" to activate"
kill $KILL_IHOOK
exit 2
fi

echo "Partitioning Completed Successfully"
sleep 1

### CLONING STAGE 3 ###

# Start Progress Bar for Cloning
echo "%BEGINPOLE"
echo "Cloning Process Is Starting"
sleep 1
### Begin the Windows cloning process onto the 2nd partition

/private/tmp/foo/windowsvista/winclone.perl --self-extract &

### Find initial progress from the winclone output
touch $PROGRESS_FILE
PROGRESS=$(tail -1 $PROGRESS_FILE)

### Loop to keep temp file location from showing in feedback window
LIMIT=14 # Upper limit
a=0

while [ $a -le "$LIMIT" ]
do
a=$(($a+1))
echo "Cloning Operation Is Starting"
sleep .5
done

### Loop to update cloning progress constantly until complete
until [ "$PROGRESS" = '100.00 percent completed' ]; do
IHOOK_PERCENT=$(tail -1 $PROGRESS_FILE | cut -c 1-3)
echo "%$IHOOK_PERCENT"
echo "Cloning Operation Is $IHOOK_PERCENT Percent Complete"
PROGRESS=$(tail -1 $PROGRESS_FILE)
sleep 3
done

echo "%100"
echo "Cloning Operation Is 100 Percent Finished"
sleep 5

echo "%ENDPOLE"
echo "Finishing Installation"
sleep 5

echo "Installation of Windows Vista completed"
sleep 5

echo "Cleaning up installation files"
sleep 5

rm -rf /private/tmp/foo
echo "Installation Completed Successfully"
sleep 2

exit

The script checks for Intel-processor, that the initial state has only one partition, that the download completes, and that partitioning was successful or else gives an error dialog and then exits.

There are two odd glitches that occur about 1 in 100 installations, both dealing with partition map issues.

The first will cause the partitioning stage to error. Seems that on the occasional Mac, there is a small error in the partition map that doesn’t rear it’s ugly head until you attempt to change the partitions. The only fix seems to be to boot from a Disk Warrior CD and rebuild. Then the installer will run fine.

The second issue is a little more frustrating and is documented by Apple. The installation will finish without any problems, but upon the first boot while holding down the ‘option’ key, the Mac won’ recognize that the Windows partition is bootable. The Startup Disk Panel will show it, all the files are on the second partition, but the Mac refuses to boot to it. Sometimes removing the partition and re-running the installer will work, sometimes not. Doing a manual clone using Winclone will usually work. Apple’s suggestion is to erase the partition and start over.

Hope this helps someone out there with any deployment problems or if they are just looking for ideas.