WinPE 4.0 - Automated Media Creation

I maintain two Windows 8 VMs for building WinPE 4.0, one for x86 and one for x64. Unlike the Windows 7 WAIK, Apparently the Windows 8 ADK can only build x86 on x86, and x64 on x64.

This Powershell 3 script is intended to be run from a network share with subdirectories containing apps (optional) and drivers (optional), and looks something like this:








Source directories contain the source files and the x86 and amd64 directories contain the expanded x86 and x64 drivers, respectively.

Run the Powershell script on each of your x86 and x64 Windows 8 ADK environments, and it will build the respective WinPE 4.0 environment and .iso file.

There is one extra step for making the USB boot sticks [ MakeWinPEMedia /UFD c:\winpe_amd64 <drive letter>: ]; You can add that to the Media function if you have the USB drive plugged in.


Build WinPE 4.0 with PowerShell 3 cmdlets
ISO: MakeWinPEMEdia /ISO c:\winpe_amd64 c:\winpe_amd64\winpe.iso
USB: MakeWinPEMedia /UFD c:\winpe_amd64 <drive letter>:

Adam Sailer
$invoke = split-path -path $myinvocation.mycommand.path -parent
$os = gwmi Win32_OperatingSystem
$proc = gwmi Win32_Processor
$arch = 'x86'
if (($proc.AddressWidth -eq 64) -and ($proc.DataWidth -eq 64))
{ $arch = 'amd64' }
$dest = "$env:SystemDrive\winpe_$arch"; $dest
$mount = "$dest\mount"
$image = "$dest\media\sources\boot.wim"
$label = "WinPE 4.0 $arch"
$unattend = @"
<?xml version="1.0" encoding="utf-8"?>
<unattend xmlns="urn:schemas-microsoft-com:unattend">
    <settings pass="windowsPE">
        <component name="Microsoft-Windows-Setup" processorArchitecture="$arch" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="">
Function Prep
    write-host "`n`n@@ Called Prep" -Fore Magenta
    $ident = $env:ProgramFiles
    if (($proc.AddressWidth -eq 64) -and ($proc.DataWidth -eq 64))
    { $ident = ${env:ProgramFiles(x86)} }
    $map = @{
        BCDBootRoot = "$ident\Windows Kits\8.0\Assessment and Deployment Kit\Deployment Tools\$arch\BCDBoot";
        DandIRoot = "$ident\Windows Kits\8.0\Assessment and Deployment Kit\Deployment Tools";
        DISMRoot = "$ident\Windows Kits\8.0\Assessment and Deployment Kit\Deployment Tools\$arch\DISM";
        HelpIndexerRoot = "$ident\Windows Kits\8.0\Assessment and Deployment Kit\Deployment Tools\HelpIndexer";
        ImagingRoot = "$ident\Windows Kits\8.0\Assessment and Deployment Kit\Deployment Tools\$arch\Imaging";
        KitsRoot = "$ident\Windows Kits\8.0\";
        OSCDImgRoot = "$ident\Windows Kits\8.0\Assessment and Deployment Kit\Deployment Tools\$arch\Oscdimg";
        #RegKeyPath = "$key\Windows Kits\Installed Roots";
        WdsmcastRoot = "$ident\Windows Kits\8.0\Assessment and Deployment Kit\Deployment Tools\$arch\Wdsmcast";
        WinPERoot = "$ident\Windows Kits\8.0\Assessment and Deployment Kit\Windows Preinstallation Environment";
        WSIMRoot = "$ident\Windows Kits\8.0\Assessment and Deployment Kit\Deployment Tools\WSIM";
    $array = $env:Path.Split(';')
    foreach ($key in $map.Keys)
    { $array += $map.$key; [System.Environment]::SetEnvironmentVariable($key, $map.$key, "process") }
    $array = $array | sort-object -unique; $array
    $path = [string]::join(';', $array)
    [System.Environment]::SetEnvironmentVariable('PATH', $path, 'process')
Function CopySource
    write-host "`n`n@@ Called CopySource" -Fore Magenta
    remove-item $dest -recurse -force -ea SilentlyContinue
    copype $arch $dest
Function MountCurrent
    write-host "`n`n@@ Called MountCurrent" -Fore Magenta
    Mount-WindowsImage –ImagePath $image –Index 1 -Path $mount
Function DismountCurrent
    write-host "`n`n@@ Called DismountCurrent" -Fore Magenta
    if (Get-WindowsImage -Mounted)
    { Dismount-WindowsImage –Path $mount -Save }
Function Packages
    write-host "`n`n@@ Called Packages" -Fore Magenta
    $lang = 'en-us'
    ## Order matters!
    $order = @(
    $packages = @()
    $order | % { $packages += @(dir $env:WinPERoot\$arch -rec -inc "$($_).cab", "$($_)_$($lang).cab" | sort-object -desc) }
    $packages | % { write-host "`n$($_.Name)"; Add-WindowsPackage -Path $mount -PackagePath $_.FullName }
Function Drivers
    write-host "`n`n@@ Called Drivers" -Fore Magenta
    DISM /image:$mount /add-driver /driver:$invoke\drivers\$arch /recurse
Function Apps
    write-host "`n`n@@ Called Media" -Fore Magenta
    copy-item $invoke\apps\$arch $mount\Apps -recurse
    $unattend | out-file -encoding ASCII $mount\unattend.xml
Function Media
    write-host "`n`n@@ Called Media" -Fore Magenta
    MakeWinPEMEdia /ISO c:\winpe_$arch c:\winpe_$arch\winpe_$arch.iso