Monthly Archives: May 2014

Creating a WinPE 5.x boot image with PowerShell

To create the WinPE 5.0 boot image you need to have Windows ADK 8.1 installed. You can download the Windows Assessment and Deployment Kit (Windows ADK) for Windows 8.1 Update here: The following are the options you can use to run adksetup.exe:


If you download Windows ADK 8.1 on a machine that already has Windows ADK 8.0 installed, you get an error and as shown above you need to use /layout option to proceed. To continue even if previous version of Windows ADK is installed, you can run the following option:

adksetup.exe /layout “C:\OfflineADK8.1”

If you ask yourself why to download Windows ADK 8.1 and use WinPE 5.0, please consider some of the new and changed functionality:

  • Profiling in feature is removed
  • WinPE 5.0 x64 supports 4 TB of RAM (still 64 GB for x86)
  • Scratchspace set automatically to 512 MB when having more than 1 GB of RAM, otherwise 32 MB
  • You can deploy OS: Windows 8.1, Windows Server 2012 R2, Windows 8, Windows Server 2012, Windows 7, or Windows Server 2008 R2.
  • Doesn’t support: Windows Vista or Windows Server 2008.
  • Scripting tools: NET Framework optional component renamed to WinPE_NetFx; PowerShell optional component renamed to WinPE_PowerShell; and Winpeshl.ini allows you to launch apps with command-line parameters in quotes.

Creating a dual-boot WinPE 5.0 boot image

Once Windows ADK 8.1 has been downloaded and installed, you can create dual-boot WinPE by running the following PowerShell script as administrator:

# Filename: DualBoot-WinPE50.ps1 -
# Date:     May, 2014
# Author:   Alex Dujakovic
# Description: PowerShell script to create dual boot WinPE
# -------------------------------------------------------------------------------
# Paths to WinPE folders
$WinPE_BuildFolder = "C:\WinPE-Plugin\WinPE50"
$WinPE_MountFolder = "C:\WinPE-Plugin\Mount"
$WinPE_Drivers = "C:\WinPE-Plugin\Drivers"
$WinPE_AppsFiles = "C:\WinPE-Plugin\Apps"
$WinPE_Combined = "C:\WinPE-Plugin\WinPE50_Combined"
$WinPE_Media = "C:\WinPE-Plugin\Media"
$amd64 = "$WinPE_BuildFolder" + "_amd64"
$x86 = "$WinPE_BuildFolder" + "_x86"

Function Make-WinPEBootWim($WinPE_Architecture){

# Paths to WinPE folders and tools
$ADK_Path = "C:\Program Files (x86)\Windows Kits\8.1\Assessment and Deployment Kit"
$WinPE_ADK_Path = $ADK_Path + "\Windows Preinstallation Environment"
$WinPE_OCs_Path = $WinPE_ADK_Path + "\$WinPE_Architecture\WinPE_OCs"
$DISM_Path = $ADK_Path + "\Deployment Tools" + "\$WinPE_Architecture\DISM"
$WinPE_BuildFolder = $WinPE_BuildFolder + "_" + $WinPE_Architecture

# Functions
Function Delete-Folder($folderPath){
    try {
        if (Test-Path -path $folderPath) {Remove-Item -Path $folderPath -Recurse -ErrorAction Stop}
        Write-Warning "Error deleting folder!"
        Write-Warning "Error: $($_.Exception.Message)"

Function Make-Directory($folderPath){
	if (!(Test-Path -path $folderPath)) {New-Item $folderPath -Type Directory}

Function WinPE-Mount($buildFolder, $mountFolder){
    & $DISM_Path\Imagex.exe /mountrw $buildFolder\winpe.wim 1 $mountFolder

Function WinPE-UnMount($mountFolder){
    & $DISM_Path\Imagex.exe /unmount /commit $mountFolder

Delete-Folder -folderPath $WinPE_BuildFolder
Delete-Folder -folderPath $WinPE_MountFolder

Make-Directory -folderPath $WinPE_BuildFolder
Make-Directory -folderPath $WinPE_MountFolder

Copy-Item "$WinPE_ADK_Path\$WinPE_Architecture\en-us\winpe.wim" $WinPE_BuildFolder

# Mount folder
WinPE-Mount -buildFolder $WinPE_BuildFolder -mountFolder $WinPE_MountFolder

# Add WinPE 5.0 optional components using ADK 8.1 version of dism.exe
& $DISM_Path\dism.exe /Image:$WinPE_MountFolder /Add-Package /PackagePath:$WinPE_OCs_Path\
& $DISM_Path\dism.exe /Image:$WinPE_MountFolder /Add-Package /PackagePath:$WinPE_OCs_Path\en-us\
& $DISM_Path\dism.exe /Image:$WinPE_MountFolder /Add-Package /PackagePath:$WinPE_OCs_Path\
& $DISM_Path\dism.exe /Image:$WinPE_MountFolder /Add-Package /PackagePath:$WinPE_OCs_Path\en-us\
& $DISM_Path\dism.exe /Image:$WinPE_MountFolder /Add-Package /PackagePath:$WinPE_OCs_Path\
& $DISM_Path\dism.exe /Image:$WinPE_MountFolder /Add-Package /PackagePath:$WinPE_OCs_Path\en-us\
& $DISM_Path\dism.exe /Image:$WinPE_MountFolder /Add-Package /PackagePath:$WinPE_OCs_Path\
& $DISM_Path\dism.exe /Image:$WinPE_MountFolder /Add-Package /PackagePath:$WinPE_OCs_Path\en-us\
& $DISM_Path\dism.exe /Image:$WinPE_MountFolder /Add-Package /PackagePath:$WinPE_OCs_Path\
& $DISM_Path\dism.exe /Image:$WinPE_MountFolder /Add-Package /PackagePath:$WinPE_OCs_Path\en-us\
& $DISM_Path\dism.exe /Image:$WinPE_MountFolder /Add-Package /PackagePath:$WinPE_OCs_Path\
& $DISM_Path\dism.exe /Image:$WinPE_MountFolder /Add-Package /PackagePath:$WinPE_OCs_Path\en-us\
& $DISM_Path\dism.exe /Image:$WinPE_MountFolder /Add-Package /PackagePath:$WinPE_OCs_Path\
& $DISM_Path\dism.exe /Image:$WinPE_MountFolder /Add-Package /PackagePath:$WinPE_OCs_Path\en-us\

# Install WinPE 5.0 Drivers
If(Test-Path -Path "$WinPE_Drivers\$WinPE_Architecture"){
    & $DISM_Path\dism.exe /Image:$WinPE_MountFolder /Add-Driver /Driver:"$WinPE_Drivers\$WinPE_Architecture" /Recurse

# Copy WinPE Application Files
If(Test-Path -Path "$WinPE_AppsFiles\$WinPE_Architecture"){
Copy-Item "$WinPE_AppsFiles\$WinPE_Architecture\*" "$WinPE_MountFolder\Windows\System32\" -Recurse

# Unmount folder
WinPE-UnMount -mountFolder $WinPE_MountFolder

Make-Directory -folderPath "$WinPE_BuildFolder\bootiso\media\sources"

Copy-Item "$WinPE_ADK_Path\$WinPE_Architecture\Media" "$WinPE_BuildFolder\bootiso" -recurse -Force
Copy-Item "$WinPE_BuildFolder\winpe.wim" "$WinPE_BuildFolder\bootiso\media\sources\boot.wim" -Force


# Make folder to combine two boot.wim files
Function Make-Directory($folderPath){
	if (!(Test-Path -path $folderPath)) {New-Item $folderPath -Type Directory}

# Modify the BCD store
Function Modify-BCD($bcdFolderPath){
$description = "WinPE5.0_x86"
$a = bcdedit /store $bcdFolderPath\Boot\BCD /enum
$bcdFirstEntry = $a[15].Substring(56,38).Trim()
If($a[22].Substring(0,15).Trim() -eq "custom:250000c2"){
   $removeMetroStyleEntry = "bcdedit --% /store $bcdFolderPath\Boot\BCD /deletevalue {default} custom:250000c2"
   Invoke-Expression $removeMetroStyleEntry
$commandEditBcdX86 = @"
bcdedit --% /store $bcdFolderPath\Boot\BCD /set {default} device ramdisk=[boot]\sources\boot_x86.wim,$($bcdFirstEntry)
bcdedit --% /store $bcdFolderPath\Boot\BCD /set {default} osdevice ramdisk=[boot]\sources\boot_x86.wim,$($bcdFirstEntry)
bcdedit --% /store $bcdFolderPath\Boot\BCD /set {default} description $description
Invoke-Expression $commandEditBcdX86

$b = bcdedit /store "$bcdFolderPath\Boot\BCD" /copy '{default}' /d "WinPE5.0_x64"
foreach($i in $b){
$bcdSecondEntry = $i.Substring(37).Replace(".","")

$commandEditBcdx64 = @"
bcdedit --% /store $bcdFolderPath\Boot\BCD /set $($bcdSecondEntry) device ramdisk=[boot]\sources\boot_x64.wim,$($bcdFirstEntry)
bcdedit --% /store $bcdFolderPath\Boot\BCD /set $($bcdSecondEntry) osdevice ramdisk=[boot]\sources\boot_x64.wim,$($bcdFirstEntry)
bcdedit --% /store $bcdFolderPath\Boot\BCD -displayorder $($bcdSecondEntry) -addlast
Invoke-Expression $commandEditBcdx64

# To create bootable WinPE x64 - Run this command only
Make-WinPEBootWim -WinPE_Architecture "amd64"

# To create bootable WinPE x 86 - Run this command only
Make-WinPEBootWim -WinPE_Architecture "x86"

# To create DualBoot WinPe x86/x64 - Run above and all the commands below as well
Make-Directory -folderPath $WinPE_Combined
Copy-Item "$x86\bootiso\media\*" -Destination $WinPE_Combined -recurse -Force
rename-item -path "$WinPE_Combined\Sources\boot.wim" -newname boot_x86.wim -Force
Copy-Item "$amd64\bootiso\media\sources\boot.wim" -Destination "$WinPE_Combined\Sources" -Force
rename-item -path "$WinPE_Combined\Sources\boot.wim" -newname boot_x64.wim -Force
rename-item -path $WinPE_Combined -newname $WinPE_Media -Force
Modify-BCD -bcdFolderPath $WinPE_Media

Please go to the Download/PowerShell section to download the above PowerShell script: DualBoot-WinPE50.ps1.

At the beginning of the script you will notice the paths to the WinPE build folders. You do not need to have these folders, but in my case, I like to have a folder that will house and keep organized all my WinPE drivers, applications and configuration files.  See the picture below that provides some info about the content of my WinPE-Plugin folder. WinPEFolders

WinPE-Plugin folder has subfolders Apps and Drivers that house 64 bit and 32 bit applications and drivers. Amd64 folder, for example contains all files and apps that I need in order to build my customized 64 bit WinPE. In one of my next blogs I will provide more info about GUI that I’ve build for WinPE that looks like the following – see this post about WinPE GUI.AlexWinPE Once the DualBoot-WinPE50.ps1 script finishes executing, it creates WinPE-Plugin folder with four subfolders: Media, Mount, WinPE50_amd64 and WinPE50_x64. In my case, as previously explained, I have additional Apps and Drivers subfolders as shown in the picture below:


To finalize creation of my dual boot WinPE I use my DiskPart application (you could find it in the download section) to build a bootable USB stick. It will format a USB drive and transfer all files from the following folder: C:\WinPE-Plugin\Media, as shown below.


At the end, I would like just to add a few lines about Make-BCD function in the script. You will notice that this function is searching BCD store for the existence of the “custom:250000c2” setting. What is the purpose of this setting in BCD? Its purpose is to tell bootmgr to go ahead and boot Windows 8 and invoke bootux.dll to display the new metro style and touch compatible boot menu. Setting that option to 0 or removing the option from the BCD entry will tell bootmgr to fall back to the behaviour we see in Vista and 7. This is why I used this function to delete this setting, and therefore have a dual boot WinPE option.

Please note: Although the author has made every reasonable attempt to achieve complete accuracy of the content, he assumes no responsibility for errors or omissions. Also, you should use this information as you see fit, and at your own risk.