If you are creating unattended.xml files to use to perform automated installations of windows then you will at some point want to test it. This is fine if the destination system has a keyboard and monitor but in my case the system I am targeting does not, a HP MediaSmart EX490.
The simplest way I found on Windows 8 to do the testing was to use the Hyper-V role. Normally I prepare a USB stick with the Microsoft USB/DVD Download Tool and then copy the autounattend.xml file to the root of the USB disk. However, during installation Windows will search for an autounattend.xml or unattend.xml on other removable devices. Using this we can setup a Hyper-V VM with two DVD drives. One with the installation media in the other with just the autounattend.xml
I found on the internet a PowerShell script, New-IsoFile that will create an ISO from a list of files. Credit goes to Chris Woo and information can be found at http://gallery.technet.microsoft.com/scriptcenter/New-ISOFile-function-a8deeffd
Below is my PowerShell script that I use. Basically it uses Chris’s New-IsoFile function to create an ISO with the autounattend.xml file in it. It then creates a VM, attaches the Installation ISO (in this case Hyper-V Server) and the answer file ISO and starts the VM.
function New-IsoFile { <# .Synopsis Creates a new .iso file .Description The New-IsoFile cmdlet creates a new .iso file containing content from chosen folders .Example New-IsoFile "c:\tools","c:Downloads\utils" Description ----------- This command creates a .iso file in $env:temp folder (default location) that contains c:\tools and c:\downloads\utils folders. The folders themselves are added in the root of the .iso image. .Example dir c:\WinPE | New-IsoFile -Path c:\temp\WinPE.iso -BootFile etfsboot.com -Media DVDPLUSR -Title "WinPE" Description ----------- This command creates a bootable .iso file containing the content from c:\WinPE folder, but the folder itself isn't included. Boot file etfsboot.com can be found in Windows AIK. Refer to IMAPI_MEDIA_PHYSICAL_TYPE enumeration for possible media types: http://msdn.microsoft.com/en-us/library/windows/desktop/aa366217(v=vs.85).aspx .Notes NAME: New-IsoFile AUTHOR: Chris Wu LASTEDIT: 03/06/2012 14:06:16 #> Param ( [parameter(Position=0,Mandatory=$true,ValueFromPipeline=$true)]$Source, [parameter(Position=1)][string]$Path = "$($env:temp)\" + (Get-Date).ToString("yyyyMMdd-HHmmss.ffff") + ".iso", [string] $BootFile = $null, [string] $Media = "Disk", [string] $Title = (Get-Date).ToString("yyyyMMdd-HHmmss.ffff"), [switch] $Force )#End Param Begin { ($cp = new-object System.CodeDom.Compiler.CompilerParameters).CompilerOptions = "/unsafe" if (!("ISOFile" -as [type])) { Add-Type -CompilerParameters $cp -TypeDefinition @" public class ISOFile { public unsafe static void Create(string Path, object Stream, int BlockSize, int TotalBlocks) { int bytes = 0; byte[] buf = new byte[BlockSize]; System.IntPtr ptr = (System.IntPtr)(&bytes); System.IO.FileStream o = System.IO.File.OpenWrite(Path); System.Runtime.InteropServices.ComTypes.IStream i = Stream as System.Runtime.InteropServices.ComTypes.IStream; if (o == null) { return; } while (TotalBlocks-- > 0) { i.Read(buf, BlockSize, ptr); o.Write(buf, 0, bytes); } o.Flush(); o.Close(); } } "@ }#End If if ($BootFile -and (Test-Path $BootFile)) { ($Stream = New-Object -ComObject ADODB.Stream).Open() $Stream.Type = 1 # adFileTypeBinary $Stream.LoadFromFile((Get-Item $BootFile).Fullname) ($Boot = New-Object -ComObject IMAPI2FS.BootOptions).AssignBootImage($Stream) }#End If $MediaType = @{CDR=2; CDRW=3; DVDRAM=5; DVDPLUSR=6; DVDPLUSRW=7; ` DVDPLUSR_DUALLAYER=8; DVDDASHR=9; DVDDASHRW=10; DVDDASHR_DUALLAYER=11; ` DISK=12; DVDPLUSRW_DUALLAYER=13; BDR=18; BDRE=19 } if ($MediaType[$Media] -eq $null) { write-debug "Unsupported Media Type: $Media"; write-debug ("Choose one from: " + $MediaType.Keys); break } ($Image = new-object -com IMAPI2FS.MsftFileSystemImage -Property @{VolumeName=$Title}).ChooseImageDefaultsForMediaType($MediaType[$Media]) if ((Test-Path $Path) -and (!$Force)) { "File Exists $Path"; break } if (!($Target = New-Item -Path $Path -ItemType File -Force)) { "Cannot create file $Path"; break } } Process { switch ($Source) { { $_ -is [string] } { $Image.Root.AddTree((Get-Item $_).FullName, $true); continue } { $_ -is [IO.FileInfo] } { $Image.Root.AddTree($_.FullName, $true); continue } { $_ -is [IO.DirectoryInfo] } { $Image.Root.AddTree($_.FullName, $true); continue } }#End switch }#End Process End { if ($Boot) { $Image.BootImageOptions=$Boot } $Result = $Image.CreateResultImage() [ISOFile]::Create($Target.FullName,$Result.ImageStream,$Result.BlockSize,$Result.TotalBlocks) $Target }#End End }#End function New-IsoFile # Begin script by Albal to create New-VM based on autounattend.xml - # Assumes all required files are in, and will be written to <USER>\Downloads # Change the below parameters if needed $path = [Environment]::GetFolderPath("UserProfile") + "\Downloads" $name = "Hyper-V Server 2012" $switch = "vSwitch" # Don't change anything below this line - ignore the errors below, just in case you run the script again without having exited expectedly Stop-VM -Name $name -Force -TurnOff Remove-VM -Name $name -Force del -Force $path\auto.iso del -Force $path\hyper-v.vhd dir $path\autounattend.xml | New-IsoFile -Path $path\auto.iso -Media CDR -Title "Unattend" New-Vm -Name $name -SwitchName $switch Set-VMProcessor -VMName $name -Count 1 Set-VMMemory -VMName $name -StartupBytes 2147483648 New-VHD -Path $path\hyper-v.vhd -SizeBytes 21474836480 Add-VMHardDiskDrive -VMName $name -Path $path\hyper-v.vhd -ControllerType IDE -ControllerNumber 0 -ControllerLocation 0 Set-VMDvdDrive -VMName $name -Path $path\en_microsoft_hyper-v_server_2012_x64_dvd_915600.iso -ControllerNumber 1 -ControllerLocation 0 Add-VMDvdDrive -VMName $name -Path $path\auto.iso -ControllerNumber 1 -ControllerLocation 1 Start-VM -Name $name echo "When you press enter the Virtual Machine will be stopped and deleted" pause Stop-VM -Name $name -Force -TurnOff Remove-VM -Name $name -Force del $path\hyper-v.vhd del $path\auto.iso
Simply run the Script and Open the VM in Hyper-V Manager, you can then verify the automated install works and if not have an easier time of debugging the situation than if you were running on a headless system.