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!

Requirements:

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:         http://www.gregorystrike.com/2010/05/17/powershell-script-to-build-a-custom-winpe-v3-0-environment/
#  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

CLS;

#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'
	Exit
}

$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\WinPE-WMI.cab"
Dism /Image:$Mount /Add-Package /PackagePath:"$WAIKInstallation\Tools\PETools\$Architecture\WinPE_FPs\$Language\WinPE-WMI_$Language.cab"
Dism /Image:$Mount /Add-Package /PackagePath:"$WAIKInstallation\Tools\PETools\$Architecture\WinPE_FPs\WinPE-Scripting.cab"
Dism /Image:$Mount /Add-Package /PackagePath:"$WAIKInstallation\Tools\PETools\$Architecture\WinPE_FPs\$Language\WinPE-Scripting_$Language.cab"
Dism /Image:$Mount /Add-Package /PackagePath:"$WAIKInstallation\Tools\PETools\$Architecture\WinPE_FPs\WinPE-HTA.cab"
Dism /Image:$Mount /Add-Package /PackagePath:"$WAIKInstallation\Tools\PETools\$Architecture\WinPE_FPs\$Language\WinPE-HTA_$Language.cab"
Dism /Image:$Mount /Add-Package /PackagePath:"$WAIKInstallation\Tools\PETools\$Architecture\WinPE_FPs\WinPE-LegacySetup.cab"
Dism /Image:$Mount /Add-Package /PackagePath:"$WAIKInstallation\Tools\PETools\$Architecture\WinPE_FPs\$Language\WinPE-LegacySetup_$Language.cab"
Dism /Image:$Mount /Add-Package /PackagePath:"$WAIKInstallation\Tools\PETools\$Architecture\WinPE_FPs\WinPE-WMI.cab"
Dism /Image:$Mount /Add-Package /PackagePath:"$WAIKInstallation\Tools\PETools\$Architecture\WinPE_FPs\$Language\WinPE-WMI_$Language.cab"

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

#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'
	REG IMPORT $file
}

REG UNLOAD HKLM\PE_Sys
REG UNLOAD HKLM\PE_Soft

#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\etfsboot.com" "$BuildDir\ISO" "$BuildDir\($TimeStamp) WinPE.iso"

Gregory Strike

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