You may also be interested in how to get the Microsoft iSCSI initiator working under WinPE. Check out my WinPE v3.0 and Microsoft iSCSI Initiator posting.

This script will build a custom WinPE v3.0 (Windows 7 based) environment and generate a bootable ISO.

It gives you the ability to import a custom startup script (Autostart.cmd), custom wallpaper, custom drivers, registry files and custom Program Files to create a WinPE environment that works for you. You no longer have to waste the time trying to remember those pesky WinPE commands. Let the script do it for you!


Windows PowerShell v1.0 or higher

Windows Automated Installation Kit (AIK) for Windows 7 (Can be installed on Windows XP, Vista, or 7)

#  Script name:    Build_WinPE.ps1
#  Created on:     2010-01-05
#  Author:         Gregory Strike
#     URL:
#  Purpose:        Builds a customized WinPE v3.0 image from scratch.

# Special Files:
# Autostart.cmd - Place a file called Autostart.cmd in the $Custom_WinPE\Program Files\System\ and it will run automatically on startup.
# winpe.bmp     - Place a file called winpe.bmp in $Custom_WinPE\Program Files\System\ and it will replace the default wallpaper.

$BuildDir = "C:\Temp\WinPE";	# No Spaces due to Microsoft's CopyPE Limitation
$Architecture = "x86"           # Architecture Target (x86, amd64, ia64)
$Language = "en-us"
$WAIKInstallation = "C:\Program Files\Windows AIK"; # Path to the WAIK Installation
$ISOLabel = "IMAGER"            # Volume label for the ISO

$Custom_WinPE = "C:\Documents and Settings\Administrator\Desktop\WinPE_Files";  # The folder for your custom files
$DriversDir = "$Custom_WinPE\Drivers";          # Any drivers you wish added to the image (recursive)
$ProgramsDir = "$Custom_WinPE\Program Files";   # Files\Folders added to "X:\Program Files" (recursive)
$WindowsDir = "$Custom_WinPE\Windows";          # Files\Folders added to "X:\Windows" (recursive)
$RegistryDIr = "$Custom_WinPE\Registry";        # Imports .REG files into the registry. (recursive)
                                                # WinPE registry hives are mounted to:
                                                #   HKLM\Software --> HLKM\PE_Sys
                                                #   HKLM\System   --> HLKM\PE_Soft
                                                # You will have to adjust your .REG files accordingly


#Ensure WAIK PETools are in the Path
#This does the same as "Windows AIK\Tools\PETools\pesetenv.cmd"
Write-Host("Checking and updating path if needed...") -Fore 'Yellow'
$Path = "";
$Path += $WAIKInstallation + "\Tools\PETools" + ";"
if ($Architecture -ne "x86"){
	$Path += $WAIKInstallation + "\Tools\x86;"
if ($Architecture -ne "x86"){
	$Path += $WAIKInstallation + "\Tools\x86\Servicing;"
$Path += $WAIKInstallation + "\Tools\" + $Architecture + ";"
$Path += $WAIKInstallation + "\Tools\" + $Architecture + "\Servicing;"
If (!$Env:Path.ToLower().Contains($Path.ToLower())){
	[System.Environment]::SetEnvironmentVariable("PATH", $Path + $Env:Path, "process")

#Does BuildPath already exist?  If so, Exit.
if (Test-Path -path $BuildDir){
	Write-Host("BuildDir: " + $BuildDir + " already exists.  The script will now exit.") -Fore 'Red'

$BootWIM = $BuildDir + "\ISO\sources\boot.wim"
$Mount = $BuildDir + "\mount"
$SystemPath = "$Mount\Windows\System32"  #System32 is used in all Architecture types for our purposes.

#Run Dism Cleanup
Write-Host("Running Imagex /Cleanup...") -Fore 'Yellow'
ImageX /Cleanup

#Run CopyPE.cmd to create the initial WinPE Image
Write-Host("Running CopyPE...") -Fore 'Yellow'
copype.cmd $Architecture $BuildDir

#Moving .WIM image to ISO\sources Folder
Write-Host("Moving WinPE.wim file to ISO\Sources\boot.wim...") -Fore 'Yellow'
Move-Item "$BuildDir\winpe.wim" "$BootWIM"

#Mounting Image
Write-Host("Mounting Boot.wim...") -Fore 'Yellow'
#Dism /Mount-Wim /WimFile:$BootWIM /Index:1 /MountDir:$Mount
ImageX /MOUNTRW "$BootWIM" 1 "$Mount"

#Adding Packages to image
Write-Host("Adding Packages...") -Fore 'Yellow'
Dism /Image:$Mount /Add-Package /PackagePath:"$WAIKInstallation\Tools\PETools\$Architecture\WinPE_FPs\"
Dism /Image:$Mount /Add-Package /PackagePath:"$WAIKInstallation\Tools\PETools\$Architecture\WinPE_FPs\$Language\WinPE-WMI_$"
Dism /Image:$Mount /Add-Package /PackagePath:"$WAIKInstallation\Tools\PETools\$Architecture\WinPE_FPs\"
Dism /Image:$Mount /Add-Package /PackagePath:"$WAIKInstallation\Tools\PETools\$Architecture\WinPE_FPs\$Language\WinPE-Scripting_$"
Dism /Image:$Mount /Add-Package /PackagePath:"$WAIKInstallation\Tools\PETools\$Architecture\WinPE_FPs\"
Dism /Image:$Mount /Add-Package /PackagePath:"$WAIKInstallation\Tools\PETools\$Architecture\WinPE_FPs\$Language\WinPE-HTA_$"
Dism /Image:$Mount /Add-Package /PackagePath:"$WAIKInstallation\Tools\PETools\$Architecture\WinPE_FPs\"
Dism /Image:$Mount /Add-Package /PackagePath:"$WAIKInstallation\Tools\PETools\$Architecture\WinPE_FPs\$Language\WinPE-LegacySetup_$"
Dism /Image:$Mount /Add-Package /PackagePath:"$WAIKInstallation\Tools\PETools\$Architecture\WinPE_FPs\"
Dism /Image:$Mount /Add-Package /PackagePath:"$WAIKInstallation\Tools\PETools\$Architecture\WinPE_FPs\$Language\WinPE-WMI_$"

#Dism /Image:$Mount /Add-Package /PackagePath:"$WAIKInstallation\Tools\PETools\$Architecture\WinPE_FPs\"
#Dism /Image:$Mount /Add-Package /PackagePath:"$WAIKInstallation\Tools\PETools\$Architecture\WinPE_FPs\$Language\WinPE-MDAC_$"
#Dism /Image:$Mount /Add-Package /PackagePath:"$WAIKInstallation\Tools\PETools\$Architecture\WinPE_FPs\"
#Dism /Image:$Mount /Add-Package /PackagePath:"$WAIKInstallation\Tools\PETools\$Architecture\WinPE_FPs\$Language\WinPE-PPPoE_$"
#Dism /Image:$Mount /Add-Package /PackagePath:"$WAIKInstallation\Tools\PETools\$Architecture\WinPE_FPs\"
#Dism /Image:$Mount /Add-Package /PackagePath:"$WAIKInstallation\Tools\PETools\$Architecture\WinPE_FPs\$Language\WinPE-Setup_$"
#Dism /Image:$Mount /Add-Package /PackagePath:"$WAIKInstallation\Tools\PETools\$Architecture\WinPE_FPs\"
#Dism /Image:$Mount /Add-Package /PackagePath:"$WAIKInstallation\Tools\PETools\$Architecture\WinPE_FPs\$Language\WinPE-Setup-Client_$"
#Dism /Image:$Mount /Add-Package /PackagePath:"$WAIKInstallation\Tools\PETools\$Architecture\WinPE_FPs\"
#Dism /Image:$Mount /Add-Package /PackagePath:"$WAIKInstallation\Tools\PETools\$Architecture\WinPE_FPs\$Language\WinPE-Setup-Server_$"
#Dism /Image:$Mount /Add-Package /PackagePath:"$WAIKInstallation\Tools\PETools\$Architecture\WinPE_FPs\"
#Dism /Image:$Mount /Add-Package /PackagePath:"$WAIKInstallation\Tools\PETools\$Architecture\WinPE_FPs\$Language\WinPE-SRT_$"
#Dism /Image:$Mount /Add-Package /PackagePath:"$WAIKInstallation\Tools\PETools\$Architecture\WinPE_FPs\"
#Dism /Image:$Mount /Add-Package /PackagePath:"$WAIKInstallation\Tools\PETools\$Architecture\WinPE_FPs\$Language\WinPE-WDS-Tools_$"

#Adding Drivers to Image
Write-Host("Installing Drivers...") -Fore 'Yellow'
Dism /Image:$Mount /Add-Driver /Driver:$DriversDir /Recurse

#Copying Program Files Folder
Write-Host("Copying Program Files...") -Fore 'Yellow'
Copy-Item $ProgramsDir\* "$Mount\Program Files" -Recurse

#Copying Windows Folder
Write-Host("Copying to Windows Directory...") -Fore 'Yellow'
Copy-Item $WindowsDir\* "$Mount\Windows" -Recurse

#Importing Custom Registry Entries
Write-Host("Importing Custom Registry Entries...") -Fore 'Yellow'
REG LOAD HKLM\PE_Sys $Mount\Windows\System32\config\SYSTEM
REG LOAD HKLM\PE_Soft $Mount\Windows\System32\config\SOFTWARE

foreach ($file in Get-ChildItem -Path "$RegistryDir\" -Recurse)
	Write-Host("...Importing $file") -Fore 'Yellow'


#If Autostart.cmd exists add it to startup.
Write-Host("Checking if $Mount\Program Files\System\Autostart.cmd exists... If so, add it to startup.") -Fore 'Yellow'
if (Test-Path -path "$Mount\Program Files\System\Autostart.cmd"){
	Write-Host("Adding Autostart.cmd to startup...") -Fore 'Yellow'
	Add-Content -Path "$SystemPath\startnet.cmd" -Value """X:\Program Files\System\Autostart.cmd"""
} else {
	Write-Host("Autostart.cmd not found...") -Fore 'Red'

#If Winpe.bmp exists replace the default wallpaper.
Write-Host("Checking if $Mount\Program Files\System\winpe.bmp exists... If so, replace wallpaper.") -Fore 'Yellow'
if (Test-Path -path "$Mount\Program Files\System\winpe.bmp"){
	Write-Host("Updating Wallpaper...") -Fore 'Yellow'
	Move-Item "$Mount\Program Files\System\winpe.bmp" "$SystemPath\winpe.bmp" -Force
} else {
	Write-Host("Wallpaper not found...") -Fore 'Red'

#Unmount image
Write-Host("Unmounting\Committing Image...") -Fore 'Yellow'
#Dism /Unmount-Wim /MountDir:$Mount /Commit
ImageX /Unmount "$Mount" /Commit

#Create ISO
Write-Host("Building ISO...") -Fore 'Yellow'
$TimeStamp = Get-Date -Format yyyy-MM-dd;
oscdimg "-n" "-l$ISOLabel" "-b$BuildDir\" "$BuildDir\ISO" "$BuildDir\($TimeStamp) WinPE.iso"

Gregory Strike

Husband, father, IT dude & blogger wrapped up into one good looking package.