jump to navigation

Penn State MacAdmins Conference 2012 May 3, 2012

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

I’m honored to represent my University as a speaker at this years MacAdmins Conference being hosted by Penn State University. I’ll be making a post in the near future, that will be a rehash of my presentation, “Automate Boot Camp Installation using BitTorrent”.

But for those that attended, here is the link for the main installer script that would need some modification to suit your environment. These scripts will need to be modified for your environment, especially the sections referenced in the presentation of the win7_installer.sh and winclone.perl pieces.

Click here to download the Windows Installer scripts and presentation.

As usual, please test, test, test. Not responsible if you blow up your director’s Mac and he sends you to Siberia.

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.