Updated Windows 10 ISO Creation Script

Several weeks ago Johan Arwidmark published an article about creating a Windows 10 ISO using the install.esd file generated from the upgrade process.  He also included a PowerShell script to automate the process.  His article can be found here.

I’ve used this a number of times and it works wonderfully.  Call me odd, but I have a set of 4 virtual machines that I use simply to generate the ISOs and installation source files.  I have a pair of Windows 10 Professional (32bit and 64bit) and a pair of Windows 10 Enterprise (32bit and 64bit) VMs.  I use the Professional SKU in my lab and the Enterprise SKU for testing at work.

I modified Johan’s original script to automate some “branding” of the process.  For example, the ISO generated includes the build number, SKU and architecture.  When a new build is released to the Fast Ring my VMs update and then I just run this script.  The script determines what build, SKU and architecture the VM is running and generates a unique name for the ISO as well as the parent folder that also contains the contents of the ISO.

$WinVer = [environment]::OSVersion.Version
$WinBuild = $WinVer.Build
$sku = $((gwmi win32_operatingsystem).OperatingSystemSKU)
switch ($sku)
{
4       {$skuName = "Ent";break}
48       {$skuName = "Pro";break}
}

switch ($env:PROCESSOR_ARCHITECTURE)
{
"x86" {$WinArch = "32" ; break}
"AMD64" {$WinArch = "64" ; break}
}
$ESDFile = 'C:\RecoveryImage\Install.esd'
$ISOMediaFolder = "C:\ISO.$WinBuild\Media"
$ISOFile = "C:\ISO.$WinBuild\Windows10$skuName`_build$WinBuild`_$WinArch.iso"
$PathToOscdimg = 'C:\oscdimg'
Write-Output "Checking for oscdimg.exe"
If (Test-Path $PathToOscdimg\oscdimg.exe)
{
Write-Output "Oscdimg.exe found, OK, continuing..."
Write-Output " "
}
Else
{
Write-Output "Oupps, cannot find Oscdimg.exe. Aborting"
Break
}

# Create ISO folder structure
New-Item -ItemType Directory $ISOMediaFolder
dism.exe /Apply-Image /ImageFile:$ESDFile /Index:1 /ApplyDir:$ISOMediaFolder

# Create empty boot.wim file with compression type set to maximum
New-Item -ItemType Directory 'C:\EmptyFolder'
dism.exe /Capture-Image /ImageFile:$ISOMediaFolder\sources\boot.wim /CaptureDir:C:\EmptyFolder /Name:EmptyIndex /Compress:max

# Export base Windows PE to empty boot.wim file (creating a second index)
dism.exe /Export-image /SourceImageFile:$ESDFile /SourceIndex:2 /DestinationImageFile:$ISOMediaFolder\sources\boot.wim /Compress:Recovery /Bootable

# Delete the first empty index in boot.wim
dism.exe /Delete-Image /ImageFile:$ISOMediaFolder\sources\boot.wim /Index:1

# Export Windows PE with Setup to boot.wim file
dism.exe /Export-image /SourceImageFile:$ESDFile /SourceIndex:3 /DestinationImageFile:$ISOMediaFolder\sources\boot.wim /Compress:Recovery /Bootable

# Display info from the created boot.wim
dism.exe /Get-WimInfo /WimFile:$ISOMediaFolder\sources\boot.wim

# Create empty install.wim file with MDT/ConfigMgr friendly compression type (maximum)
dism.exe /Capture-Image /ImageFile:$ISOMediaFolder\sources\install.wim /CaptureDir:C:\EmptyFolder /Name:EmptyIndex /Compress:max

# Export Windows Technical Preview to empty install.wim file
dism.exe /Export-image /SourceImageFile:$ESDFile /SourceIndex:4 /DestinationImageFile:$ISOMediaFolder\sources\install.wim /Compress:Recovery

# Delete the first empty index in install.wim
dism.exe /Delete-Image /ImageFile:$ISOMediaFolder\sources\install.wim /Index:1

# Display info from the created install.wim
dism.exe /Get-WimInfo /WimFile:$ISOMediaFolder\sources\install.wim

# Create the Windows Technical Preview ISO
# For more info on the Oscdimg.exe commands, check this post: http://support2.microsoft.com/kb/947024
$BootData='2#p0,e,b"{0}"#pEF,e,b"{1}"' -f "$ISOMediaFolder\boot\etfsboot.com","$ISOMediaFolder\efi\Microsoft\boot\efisys.bin"

$Proc = Start-Process -FilePath "$PathToOscdimg\oscdimg.exe" -ArgumentList @("-bootdata:$BootData",'-u2','-udfver102',"$ISOMediaFolder","$ISOFile") -PassThru -Wait -NoNewWindow

if($Proc.ExitCode -ne 0)
{
Throw "Failed to generate ISO with exitcode: $($Proc.ExitCode)"
}

The heart of Johan’s script has been untouched.  My modifications are all within the first 20 lines.

I first pull the build number from the environment variable.

$WinVer = [environment]::OSVersion.Version
$WinBuild = $WinVer.Build

I then use WMI to determine what SKU is running on the VM.


$sku = $((gwmi win32_operatingsystem).OperatingSystemSKU)
switch ($sku)
{
4       {$skuName = "Ent";break}
48       {$skuName = "Pro";break}
}

Then, a check of the environment variable to discover what architecture we have.


switch ($env:PROCESSOR_ARCHITECTURE)
{
"x86" {$WinArch = "32" ; break}
"AMD64" {$WinArch = "64" ; break}
}

From there it’s just a matter of putting the variables together to generate the unique ISO filename and folder.


$ESDFile = 'C:\RecoveryImage\Install.esd'
$ISOMediaFolder = "C:\ISO.$WinBuild\Media"
$ISOFile = "C:\ISO.$WinBuild\Windows10$skuName`_build$WinBuild`_$WinArch.iso"
$PathToOscdimg = 'C:\oscdimg'

With this I don’t have to modify the script with each build release or have different scripts for the different SKUs and architectures.

Advertisements

Posted on April 25, 2015, in Handy to Have, PowerShell, Windows 10 and tagged , , . Bookmark the permalink. Leave a comment.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: